1
struct data{
char *key;
char *fname;
char *lname;
char *grade;
struct data *next;
};


 newnode = (struct data*)malloc(sizeof(struct data));
 strcpy(newnode->lname,lname);
 strcpy(newnode->grade,grade);
 strcpy(newnode->key,key);
 strcpy(newnode->fname,fname);
 newnode->next=NULL;

So i was working on hashtables. The above code crashes while

struct data *newnode;
newnode = (struct data*)malloc(sizeof(struct data));
newnode->lname=(char*)malloc(strlen(lname)+1);
newnode->fname=(char*)malloc(strlen(fname)+1);
newnode->grade=(char*)malloc(strlen(grade)+1);
newnode->key=(char*)malloc(strlen(key)+1);

strcpy(newnode->lname,lname);
strcpy(newnode->grade,grade);
strcpy(newnode->key,key);
strcpy(newnode->fname,fname);
newnode->next=NULL;

this code seems to run. Why is that? As far as i understand i've already allocated memory for my struct in the heap. Why would i have to do it for each object specifically? Is there something else im missing? Cause i really don't understand why the bottom example would work.

Kyon Bugsy
  • 33
  • 9

3 Answers3

4

When you do

newnode = malloc(sizeof(struct data));

you only allocate memory for the actual structure. But since the structure contains pointers, you need to make those pointers point somewhere valid. The single malloc call doesn't know anything about the contents of the structure, or how much extra memory it should allocate for all the pointers.

If, for example, you declare a single normal pointer variable you would not expect to be able to just use it as a destination for a strcpy call without allocating memory, would you?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
4

With newnode = (struct data*)malloc(sizeof(struct data)), you allocate memory only for struct data, which is a set of pointers, but you do not allocate any memory for that where these pointers are pointing to and where you will copy your strings to. So you have to allocate memory for each string separately, either by using malloc as in the second part of your question, or by using strdup, which does malloc and strcpy in one command:

struct data{
char *key;
char *fname;
char *lname;
char *grade;
struct data *next;
};


 newnode = (struct data*)malloc(sizeof(struct data));
 newnode->lname = strdup(lname);
 newnode-> grade = strdup(grade);
 newnode-> key = strdup(key);
 newnode-> fname = strdup(fname);
 newnode->next=NULL;

It's worth noting that strdup requires a string as input, i.e. a pointer that is not NULL and that points to a \0-terminated sequence of characters.

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
0

When you malloc a structure with char * inside it doesn't point anywhere (at least is NULL) so you've to malloc it as a normal sequence of characters also because you must know the size of the destination string. You can do it in your way using malloc and strcpy or just strdup.

simo-r
  • 733
  • 1
  • 9
  • 13
  • 1
    `strncpy()` is terrible for most uses - you need to jump through hoops to ensure that the destination is properly terminated. – Michael Burr May 31 '17 at 06:46
  • @MichaelBurr If the source string is properly terminated and you use strncpy in the right way it improves security and robustness of you code avoiding buffer overflows. – simo-r May 31 '17 at 06:52
  • 1
    @BetaRunner, strncpy has it's uses, but not as a "safe" version of strcpy. Sadly it's a much misunderstood function. Also the buffer returned by malloc may contain garbage, so there's no guarantee that the pointers in the stuct are NULL. Most likely they are not. – harald May 31 '17 at 17:53
  • @BetaRunner: Microsoft [disallows `strncpy()` in their own code](https://msdn.microsoft.com/en-us/library/bb288454.aspx) (and newer MSVC compilers warn about it by default for everyone) because of documented problems in its use. And here's [a quote from Linus Torvalds about `strncpy()`](http://yarchive.net/comp/linux/strncpy.html): "`strncpy()` is a frigging disaster when it comes to '\0', in many ways. We should probably disallow using `strncpy()`" – Michael Burr May 31 '17 at 20:01
  • You're right guys, I read a lot about it now and I agree with you. – simo-r May 31 '17 at 20:04