user2719875 user2719875 -3 years ago 129
C Question

multiple node values all point to the same value even when using malloc and strcpy

Edit: just trying to learn C and coming from a Python background, hopefully I don't get downvoted too much for this.

I have this struct:

struct TreeNode {
char *value;
struct TreeNode *sibling;
struct TreeNode *child;
};


I have this code to create nodes:

struct TreeNode* create_node(const char* value) {
struct TreeNode node;
node.value = malloc(sizeof(char) * (strlen(value) + 1));
strcpy(node.value, value);
node.sibling = NULL;
node.child = NULL;
struct TreeNode* node_ptr = &node;
return node_ptr;
}


and this is the code in another function which creates the node (where values is an array of strings):

struct TreeNode a = create_node(values[0]);
struct TreeNode b = create_node(values[1]);
struct TreeNode c = create_node(values[2]);
struct TreeNode d = create_node(values[3]);
printf("%s\n", a->value);
printf("%s\n", b->value);
printf("%s\n", c->value);
printf("%s\n", d->value);


When I compile and run this, it prints
values[3]
four times (meaning the value for node a, b, c and d are all
values[3]
).

Question 1) Why do they all have the same value?

Note: Code which works properly is:

struct TreeNode* create_node(const char* value) {
struct TreeNode* node = malloc(sizeof(struct TreeNode));
node->value = malloc(strlen(value) + 1);
strcpy(node->value, value);
node->child = NULL;
node->sibling = NULL;
return node;
}


Question 2) Why does the latter work, and the former doesn't?

Question 3) In the latter, shouldn't it be
node->value = malloc(sizeof(char) * (strlen(value) + 1));
rather than just
node->value = malloc(strlen(value) + 1);
?

Answer Source

2) Why does the latter work, and the former doesn't?

Becouse you are returning address of local variable. In the time you are dereferencing pointer is the local variable out of scope (ended it's lifetime) which leads to undefined behavior. In function you have to return pointer only to variable(declared in function) with dynamic storage duration.


3) In the latter, shouldn't it be node->value = malloc(sizeof(char) * (strlen(value) + 1)); rather than just node->value = malloc(strlen(value) + 1);

Size of char is 1B by standard.

C99, section 6.5.3.4

When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1.


1) Why do they all have the same value?

Becouse UB, change create_node to:

struct TreeNode* create_node(const char* value)
{
    struct TreeNode * node = (struct TreeNode*)malloc (sizeof(struct TreeNode));
    node->value = malloc(sizeof(char) * (strlen(value) + 1));
    strcpy(node->value, value);
    node->sibling = NULL;
    node->child = NULL;
    return node;
}

and it won't :-)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download