Why does the strcpy() function produce unwanted outputs in the case of this program?
I am trying to create a linked list in C and this post refers to the part where I try to assign a variable in a structure a string value that the user inputs. The program compiles perfectly yet if I use strcpy() instead of strdup() then I get unwanted output.
The program compiles fine and gives no warnings or errors. If strdup() is used then the program works as intended but I'd like to know why it doesn't work when strcpy() is used instead. When passing in strings for the names, when the list is printed it will occasionally print null and then terminate or it will instead print "Name:Name:Name:Name:Nam" or other such unpredictable errors. Any other comments or criticisms would be appreciated as well as I am just starting to learn the language, thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct addressBook {
char *name;
int age;
char *phoneNumber;
struct addressBook *next;
};
static struct addressBook *head = NULL;
static struct addressBook *current;
static struct addressBook *createNew;
//function prototypes
void addNode(void);
struct addressBook * createNode(void);
void printAddressBook(void);
void printStats(void);
int main(void)
{
addNode();
addNode();
printAddressBook();
addNode();
addNode();
printAddressBook();
}
struct addressBook * createNode(void)
{
struct addressBook *newNode;
newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
if (newNode == NULL)
{
puts("Memory error");
exit(1);
}
printf("nEnter persons name: ");
char name[20];
scanf("%s", name);
strcpy(newNode -> name, name); //produces unpredictable results
//newNode -> name = strdup(name); Works fine with strdup
printf("Enter persons age: ");
scanf("%d", &newNode -> age);
printf("Enter persons phone number: ");
char phoneNumber[15];
scanf("%s", phoneNumber);
strcpy(newNode -> phoneNumber, phoneNumber); //produces unpredictable
results
//newNode -> phoneNumber = strdup(phoneNumber); Works fine with strdup
return(newNode);
}
void addNode(void)
{
createNew = createNode();
current = createNew;
current -> next = head;
head = current;
}
void printAddressBook(void)
{
struct addressBook *temp;
temp = head;
while(temp)
{
printf("Name: %snAge: %dnPhoneNumber: %snnn",
temp -> name,
temp -> age,
temp -> phoneNumber);
temp = temp -> next;
}
}
c string linked-list
add a comment |
I am trying to create a linked list in C and this post refers to the part where I try to assign a variable in a structure a string value that the user inputs. The program compiles perfectly yet if I use strcpy() instead of strdup() then I get unwanted output.
The program compiles fine and gives no warnings or errors. If strdup() is used then the program works as intended but I'd like to know why it doesn't work when strcpy() is used instead. When passing in strings for the names, when the list is printed it will occasionally print null and then terminate or it will instead print "Name:Name:Name:Name:Nam" or other such unpredictable errors. Any other comments or criticisms would be appreciated as well as I am just starting to learn the language, thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct addressBook {
char *name;
int age;
char *phoneNumber;
struct addressBook *next;
};
static struct addressBook *head = NULL;
static struct addressBook *current;
static struct addressBook *createNew;
//function prototypes
void addNode(void);
struct addressBook * createNode(void);
void printAddressBook(void);
void printStats(void);
int main(void)
{
addNode();
addNode();
printAddressBook();
addNode();
addNode();
printAddressBook();
}
struct addressBook * createNode(void)
{
struct addressBook *newNode;
newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
if (newNode == NULL)
{
puts("Memory error");
exit(1);
}
printf("nEnter persons name: ");
char name[20];
scanf("%s", name);
strcpy(newNode -> name, name); //produces unpredictable results
//newNode -> name = strdup(name); Works fine with strdup
printf("Enter persons age: ");
scanf("%d", &newNode -> age);
printf("Enter persons phone number: ");
char phoneNumber[15];
scanf("%s", phoneNumber);
strcpy(newNode -> phoneNumber, phoneNumber); //produces unpredictable
results
//newNode -> phoneNumber = strdup(phoneNumber); Works fine with strdup
return(newNode);
}
void addNode(void)
{
createNew = createNode();
current = createNew;
current -> next = head;
head = current;
}
void printAddressBook(void)
{
struct addressBook *temp;
temp = head;
while(temp)
{
printf("Name: %snAge: %dnPhoneNumber: %snnn",
temp -> name,
temp -> age,
temp -> phoneNumber);
temp = temp -> next;
}
}
c string linked-list
1
OT: for ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces.
– user3629249
Dec 30 '18 at 21:04
1
OT: when calling any of the heap allocation functions:malloc
calloc
realloc
1) in C, the returned type isvoid*
which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. I.E. this:newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
should be:newNode = malloc(sizeof(struct addressBook));
– user3629249
Dec 30 '18 at 21:06
the posted code has a massive memory leak. Every memory allocation 'should' be matched with a call to 'free()` before the program exits. I.E. to do write code that requires the OS to cleanup afterward
– user3629249
Dec 30 '18 at 21:08
1
OT: when calling any of thescanf()
family of functions. 1) always check the returned value to assure the operation was successful. 2) when using the input format specifiers: '%s' and/or '%[...]' always use a MAX CHARACTERS modifier that is 1 less than the length of the input buffer because those specifiers always append a NUL byte to the input. This avoid a possibility of a buffer overflow and the resulting undefined behavior
– user3629249
Dec 30 '18 at 21:11
add a comment |
I am trying to create a linked list in C and this post refers to the part where I try to assign a variable in a structure a string value that the user inputs. The program compiles perfectly yet if I use strcpy() instead of strdup() then I get unwanted output.
The program compiles fine and gives no warnings or errors. If strdup() is used then the program works as intended but I'd like to know why it doesn't work when strcpy() is used instead. When passing in strings for the names, when the list is printed it will occasionally print null and then terminate or it will instead print "Name:Name:Name:Name:Nam" or other such unpredictable errors. Any other comments or criticisms would be appreciated as well as I am just starting to learn the language, thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct addressBook {
char *name;
int age;
char *phoneNumber;
struct addressBook *next;
};
static struct addressBook *head = NULL;
static struct addressBook *current;
static struct addressBook *createNew;
//function prototypes
void addNode(void);
struct addressBook * createNode(void);
void printAddressBook(void);
void printStats(void);
int main(void)
{
addNode();
addNode();
printAddressBook();
addNode();
addNode();
printAddressBook();
}
struct addressBook * createNode(void)
{
struct addressBook *newNode;
newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
if (newNode == NULL)
{
puts("Memory error");
exit(1);
}
printf("nEnter persons name: ");
char name[20];
scanf("%s", name);
strcpy(newNode -> name, name); //produces unpredictable results
//newNode -> name = strdup(name); Works fine with strdup
printf("Enter persons age: ");
scanf("%d", &newNode -> age);
printf("Enter persons phone number: ");
char phoneNumber[15];
scanf("%s", phoneNumber);
strcpy(newNode -> phoneNumber, phoneNumber); //produces unpredictable
results
//newNode -> phoneNumber = strdup(phoneNumber); Works fine with strdup
return(newNode);
}
void addNode(void)
{
createNew = createNode();
current = createNew;
current -> next = head;
head = current;
}
void printAddressBook(void)
{
struct addressBook *temp;
temp = head;
while(temp)
{
printf("Name: %snAge: %dnPhoneNumber: %snnn",
temp -> name,
temp -> age,
temp -> phoneNumber);
temp = temp -> next;
}
}
c string linked-list
I am trying to create a linked list in C and this post refers to the part where I try to assign a variable in a structure a string value that the user inputs. The program compiles perfectly yet if I use strcpy() instead of strdup() then I get unwanted output.
The program compiles fine and gives no warnings or errors. If strdup() is used then the program works as intended but I'd like to know why it doesn't work when strcpy() is used instead. When passing in strings for the names, when the list is printed it will occasionally print null and then terminate or it will instead print "Name:Name:Name:Name:Nam" or other such unpredictable errors. Any other comments or criticisms would be appreciated as well as I am just starting to learn the language, thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct addressBook {
char *name;
int age;
char *phoneNumber;
struct addressBook *next;
};
static struct addressBook *head = NULL;
static struct addressBook *current;
static struct addressBook *createNew;
//function prototypes
void addNode(void);
struct addressBook * createNode(void);
void printAddressBook(void);
void printStats(void);
int main(void)
{
addNode();
addNode();
printAddressBook();
addNode();
addNode();
printAddressBook();
}
struct addressBook * createNode(void)
{
struct addressBook *newNode;
newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
if (newNode == NULL)
{
puts("Memory error");
exit(1);
}
printf("nEnter persons name: ");
char name[20];
scanf("%s", name);
strcpy(newNode -> name, name); //produces unpredictable results
//newNode -> name = strdup(name); Works fine with strdup
printf("Enter persons age: ");
scanf("%d", &newNode -> age);
printf("Enter persons phone number: ");
char phoneNumber[15];
scanf("%s", phoneNumber);
strcpy(newNode -> phoneNumber, phoneNumber); //produces unpredictable
results
//newNode -> phoneNumber = strdup(phoneNumber); Works fine with strdup
return(newNode);
}
void addNode(void)
{
createNew = createNode();
current = createNew;
current -> next = head;
head = current;
}
void printAddressBook(void)
{
struct addressBook *temp;
temp = head;
while(temp)
{
printf("Name: %snAge: %dnPhoneNumber: %snnn",
temp -> name,
temp -> age,
temp -> phoneNumber);
temp = temp -> next;
}
}
c string linked-list
c string linked-list
asked Dec 29 '18 at 5:53
chak.koppula199chak.koppula199
11
11
1
OT: for ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces.
– user3629249
Dec 30 '18 at 21:04
1
OT: when calling any of the heap allocation functions:malloc
calloc
realloc
1) in C, the returned type isvoid*
which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. I.E. this:newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
should be:newNode = malloc(sizeof(struct addressBook));
– user3629249
Dec 30 '18 at 21:06
the posted code has a massive memory leak. Every memory allocation 'should' be matched with a call to 'free()` before the program exits. I.E. to do write code that requires the OS to cleanup afterward
– user3629249
Dec 30 '18 at 21:08
1
OT: when calling any of thescanf()
family of functions. 1) always check the returned value to assure the operation was successful. 2) when using the input format specifiers: '%s' and/or '%[...]' always use a MAX CHARACTERS modifier that is 1 less than the length of the input buffer because those specifiers always append a NUL byte to the input. This avoid a possibility of a buffer overflow and the resulting undefined behavior
– user3629249
Dec 30 '18 at 21:11
add a comment |
1
OT: for ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces.
– user3629249
Dec 30 '18 at 21:04
1
OT: when calling any of the heap allocation functions:malloc
calloc
realloc
1) in C, the returned type isvoid*
which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. I.E. this:newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
should be:newNode = malloc(sizeof(struct addressBook));
– user3629249
Dec 30 '18 at 21:06
the posted code has a massive memory leak. Every memory allocation 'should' be matched with a call to 'free()` before the program exits. I.E. to do write code that requires the OS to cleanup afterward
– user3629249
Dec 30 '18 at 21:08
1
OT: when calling any of thescanf()
family of functions. 1) always check the returned value to assure the operation was successful. 2) when using the input format specifiers: '%s' and/or '%[...]' always use a MAX CHARACTERS modifier that is 1 less than the length of the input buffer because those specifiers always append a NUL byte to the input. This avoid a possibility of a buffer overflow and the resulting undefined behavior
– user3629249
Dec 30 '18 at 21:11
1
1
OT: for ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces.
– user3629249
Dec 30 '18 at 21:04
OT: for ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces.
– user3629249
Dec 30 '18 at 21:04
1
1
OT: when calling any of the heap allocation functions:
malloc
calloc
realloc
1) in C, the returned type is void*
which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. I.E. this: newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
should be: newNode = malloc(sizeof(struct addressBook));
– user3629249
Dec 30 '18 at 21:06
OT: when calling any of the heap allocation functions:
malloc
calloc
realloc
1) in C, the returned type is void*
which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. I.E. this: newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
should be: newNode = malloc(sizeof(struct addressBook));
– user3629249
Dec 30 '18 at 21:06
the posted code has a massive memory leak. Every memory allocation 'should' be matched with a call to 'free()` before the program exits. I.E. to do write code that requires the OS to cleanup afterward
– user3629249
Dec 30 '18 at 21:08
the posted code has a massive memory leak. Every memory allocation 'should' be matched with a call to 'free()` before the program exits. I.E. to do write code that requires the OS to cleanup afterward
– user3629249
Dec 30 '18 at 21:08
1
1
OT: when calling any of the
scanf()
family of functions. 1) always check the returned value to assure the operation was successful. 2) when using the input format specifiers: '%s' and/or '%[...]' always use a MAX CHARACTERS modifier that is 1 less than the length of the input buffer because those specifiers always append a NUL byte to the input. This avoid a possibility of a buffer overflow and the resulting undefined behavior– user3629249
Dec 30 '18 at 21:11
OT: when calling any of the
scanf()
family of functions. 1) always check the returned value to assure the operation was successful. 2) when using the input format specifiers: '%s' and/or '%[...]' always use a MAX CHARACTERS modifier that is 1 less than the length of the input buffer because those specifiers always append a NUL byte to the input. This avoid a possibility of a buffer overflow and the resulting undefined behavior– user3629249
Dec 30 '18 at 21:11
add a comment |
1 Answer
1
active
oldest
votes
When you define a pointer like char *name;
it points to some random location as you haven't initialized it. It is illegal to write to the pointer and doing so will invoke Undefined Behavior.
strcpy
basically writes the string to this random pointer location invoking UB.strdup
on the other hand, allocates the required memory dynamically for the string, copies the string to that location and then returns the start of the location. You can read/write to this memory location and hence, this is valid.
Makes perfect sense, thank you so much!
– chak.koppula199
Dec 29 '18 at 13:41
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53967081%2fwhy-does-the-strcpy-function-produce-unwanted-outputs-in-the-case-of-this-prog%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
When you define a pointer like char *name;
it points to some random location as you haven't initialized it. It is illegal to write to the pointer and doing so will invoke Undefined Behavior.
strcpy
basically writes the string to this random pointer location invoking UB.strdup
on the other hand, allocates the required memory dynamically for the string, copies the string to that location and then returns the start of the location. You can read/write to this memory location and hence, this is valid.
Makes perfect sense, thank you so much!
– chak.koppula199
Dec 29 '18 at 13:41
add a comment |
When you define a pointer like char *name;
it points to some random location as you haven't initialized it. It is illegal to write to the pointer and doing so will invoke Undefined Behavior.
strcpy
basically writes the string to this random pointer location invoking UB.strdup
on the other hand, allocates the required memory dynamically for the string, copies the string to that location and then returns the start of the location. You can read/write to this memory location and hence, this is valid.
Makes perfect sense, thank you so much!
– chak.koppula199
Dec 29 '18 at 13:41
add a comment |
When you define a pointer like char *name;
it points to some random location as you haven't initialized it. It is illegal to write to the pointer and doing so will invoke Undefined Behavior.
strcpy
basically writes the string to this random pointer location invoking UB.strdup
on the other hand, allocates the required memory dynamically for the string, copies the string to that location and then returns the start of the location. You can read/write to this memory location and hence, this is valid.
When you define a pointer like char *name;
it points to some random location as you haven't initialized it. It is illegal to write to the pointer and doing so will invoke Undefined Behavior.
strcpy
basically writes the string to this random pointer location invoking UB.strdup
on the other hand, allocates the required memory dynamically for the string, copies the string to that location and then returns the start of the location. You can read/write to this memory location and hence, this is valid.
answered Dec 29 '18 at 6:02
SpikatrixSpikatrix
17.4k62660
17.4k62660
Makes perfect sense, thank you so much!
– chak.koppula199
Dec 29 '18 at 13:41
add a comment |
Makes perfect sense, thank you so much!
– chak.koppula199
Dec 29 '18 at 13:41
Makes perfect sense, thank you so much!
– chak.koppula199
Dec 29 '18 at 13:41
Makes perfect sense, thank you so much!
– chak.koppula199
Dec 29 '18 at 13:41
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53967081%2fwhy-does-the-strcpy-function-produce-unwanted-outputs-in-the-case-of-this-prog%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
OT: for ease of readability and understanding: 1) Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces.
– user3629249
Dec 30 '18 at 21:04
1
OT: when calling any of the heap allocation functions:
malloc
calloc
realloc
1) in C, the returned type isvoid*
which can be assigned to any pointer. Casting just clutters the code, making it more difficult to understand, debug, etc. I.E. this:newNode = (struct addressBook *) malloc(sizeof(struct addressBook));
should be:newNode = malloc(sizeof(struct addressBook));
– user3629249
Dec 30 '18 at 21:06
the posted code has a massive memory leak. Every memory allocation 'should' be matched with a call to 'free()` before the program exits. I.E. to do write code that requires the OS to cleanup afterward
– user3629249
Dec 30 '18 at 21:08
1
OT: when calling any of the
scanf()
family of functions. 1) always check the returned value to assure the operation was successful. 2) when using the input format specifiers: '%s' and/or '%[...]' always use a MAX CHARACTERS modifier that is 1 less than the length of the input buffer because those specifiers always append a NUL byte to the input. This avoid a possibility of a buffer overflow and the resulting undefined behavior– user3629249
Dec 30 '18 at 21:11