Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly malloc for array of struct in C

Tags:

I will read in two set of char* (or strings) using strtok, and since those two set of chars are related, (address : command\n) I decided to use a structure.

struct line* array = (struct line*)malloc(sizeof(file) * sizeof(struct line*)); 

This line mallocing space for the function gives me a segmentation fault and was wondering if you can tell me a proper way to malloc space for it. For context, here is the rest of my code:

struct line {     char* addr;     char* inst; }; while loop{     x = strtok(line,": ");     y = strtok(NULL,"\n");     strcpy(array[i].addr,x); //assume that x and y are always 3characters     strcpy(array[i].inst,++y);     i++; } 
like image 810
o0tomato0o Avatar asked Oct 27 '13 01:10

o0tomato0o


People also ask

Can you store a struct in an array?

A structure may contain elements of different data types – int, char, float, double, etc. It may also contain an array as its member. Such an array is called an array within a structure. An array within a structure is a member of the structure and can be accessed just as we access other elements of the structure.

Can you malloc an array in C?

In c programming, the array is used to store a range of values of the same data type and it occupies some space in memory which can be either static or dynamic. The malloc is a function used in the c programming for dynamic memory allocation.

How do you dynamically allocate a struct?

To allocate a new person in the myperson argument, we use the following syntax: person * myperson = (person *) malloc(sizeof(person)); This tells the compiler that we want to dynamically allocate just enough to hold a person struct in memory and then return a pointer of type person to the newly allocated data.

How do you create a malloc struct?

Suppose I want to define a structure representing length of the vector and its values as: struct Vector{ double* x; int n; }; Now, suppose I want to define a vector y and allocate memory for it. struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));


2 Answers

Allocating works the same for all types. If you need to allocate an array of line structs, you do that with:

struct line* array = malloc(number_of_elements * sizeof(struct line)); 

In your code, you were allocating an array that had the appropriate size for line pointers, not for line structs. Also note that there is no reason to cast the return value of malloc().

Note that's it's better style to use:

sizeof(*array) 

instead of:

sizeof(struct line) 

The reason for this is that the allocation will still work as intended in case you change the type of array. In this case this is unlikely, but it's just a general thing worth getting used to.

Also note that it's possible to avoid having to repeat the word struct over and over again, by typedefing the struct:

typedef struct line {     char* addr;     char* inst; } line; 

You can then just do:

line* array = malloc(number_of_elements * sizeof(*array)); 

Of course don't forget to also allocate memory for array.addr and array.inst.

like image 67
Nikos C. Avatar answered Sep 20 '22 18:09

Nikos C.


For what you have described, You do not need to allocate memory for your struct, rather, you need to allocate memory for the members char *addr;, and char *inst;. If you want to have a single copy of that structure, the first section of code illustrates how to initialize, and assign values. If you want an array, the second code example illustrates the differences.

This illustrates how to allocate memory for the members of a single struct line:

typedef struct {     char* addr;     char* inst; }LINE;  LINE line;    int main(void) {         strcpy(line.addr, "anystring"); //will fail     line.addr = malloc(80);     line.inst = malloc(80);     strcpy(line.addr, "someString");//success;     strcpy(line.inst, "someOtherString");//success;  } 

For array of struct line...

typedef struct {     char* addr;     char* inst; }LINE;  //same struct definition  LINE line[10]; //but create an array of line here.  int main(void) {        int i;          for(i=0;i<10;i++)     {       line[i].addr = malloc(80);       line[i].inst = malloc(80);     }      for(i=0;i<10;i++)     {         strcpy(line[i].addr, "someString");         strcpy(line[i].inst, "someOtherString");     }     //when done, free memory     for(i=0;i<10;i++)     {         free(line[i].addr);         free(line[i].inst);     }         } 

Added to address comment
Addressing the comment under this answer from @Adam Liss, the following code illustrates the following improvements using strdup(): 1) Uses only memory needed. 2) Performs memory creation and copy operations in one step, so the the following blocks:

for(i=0;i<10;i++) {   line[i].addr = malloc(80);   line[i].inst = malloc(80); }  for(i=0;i<10;i++) {     strcpy(line[i].addr, "someString");     strcpy(line[i].inst, "someOtherString"); } 

Become:

for(i=0;i<10;i++) {   line[i].addr = strdup("someString");   line[i].inst = strdup("someOtherString"); } 

One more note: Error handling was not included in examples above to avoid muddling up focus on the main concepts: But for the sake of completeness, because both malloc() and strdup() can fail, actual usage for each of these two functions, should include a test before using, eg:

Rather than

  line[i].addr = strdup("someString");   line[i].inst = strdup("someOtherString"); 

The code should include

  line[i].addr = strdup("someString");   if(!line[i].addr)   {       //error handling code here   }   line[i].inst = strdup("someOtherString");   if(!line[i].inst)   {       //error handling code here   } 
like image 37
ryyker Avatar answered Sep 22 '22 18:09

ryyker