1
votes
airPdata **airport = malloc(sizeof(airport) * (50+1));
    printf("Passes airPdata **airport\n");
//  buffer = malloc(sizeof(char) * (50+1));

// puts the strings into char line
while(fgets(line, 1024, fp) != NULL)
{
    // has pointer value point to line
    value = line;
    printf("Before creating space for struct members\n");
    // creating space for the struct members
    airport[j]->LocID = malloc(sizeof(char)*(50+1));

    airport[j]->fieldName = malloc(sizeof(char)*(50+1));

    airport[j]->city = malloc(sizeof(char)*(50+1));

    printf("after\n");

I'm trying to create an array of structures, but I just can't figure out how to allocate memory for the members of the struct.. It keeps segfaulting. LocID, fieldName and city are all char*

EDIT*** I figured out the problem. Using a double pointer doesn't need to allocate airport, but the members of airport still need to be allocated.

// allocates memory for the struct airPdata **airport;

// buffer = malloc(sizeof(char) * (50+1));

// puts the strings into char line
while(fgets(line, 1024, fp) != NULL)
{
    // has pointer value point to line
    value = line;
printf("Yes\n");
    // creating space for the struct members
    airport[j]->LocID = malloc(sizeof(char)*(50+1));    
    airport[j]->fieldName = malloc(sizeof(char)*(50+1));
    airport[j]->city = malloc(sizeof(char)*(50+1));
    j++;
 }

However, the program seg faults when it goes back around the while loop for the second time and encounters airport[j]->LocID = malloc

2
airPdata *airport = malloc(sizeof(*airport) * (50+1)); not ** - 0___________
I originally used airPdata airport[MAX]; because I want to use an array of structs, but changed it to a double pointer - ancd3ea4
airPdata *airport[MAX] is the array of pointers, not an array of structs - S.M.
Make up your mind--airport can be either an array of pointers, which you allocate and then allocate each element as well; or it can be just a flat array of structs, allocated once (and then use airport[i].city instead of ->) - Lee Daniel Crocker
I want to use an array of pointers, not structs then, sorry - ancd3ea4

2 Answers

1
votes

OP's code biggest failing is not allocating memory for each airport[i]


With airPdata **airport and I want to use an array of pointers, code needs to allocate at 2 levels and use an arrray.

Memory for array airport[]
Memory allocated & assigned to each element of airport[i] (OP missed this part.)
Memory allocated & assigned to the various members like airport[i].LocID


Memory for array airport is easy as shown below. airPdata **airport is a pointer and not an array. Instead use an array as that is the stated design goal.

// define array element count. 
#define AIRPORT_N 100 
// Declare the array.
airPdata *airport[AIRPORT_N];
// Keep tack of how much of the array is used.
size_t n = 0;

Now assign, read and begin filling the array, allocating as needed.

#define AIRPORT_STRING_SIZE (50 + 1)
char line[1024];
while(n < AIRPORT_N && fgets(line, sizeof line, fp)) {
  // Allocate memory for one element of `airport`
  // Notice no cast nor type coded here.
  airport[n] = malloc(sizeof *(airport[n]));
  if (airport[n] == NULL) {
    // Something simple for now.
    fprintf(stderr, "OOM\n");
    break;
  }
  // Create space for each string,  
  // TODO: add check for Out-of-Memory
  airport[n]->LocID = malloc(AIRPORT_STRING_SIZE);
  airport[n]->fieldName = malloc(AIRPORT_STRING_SIZE);
  airport[n]->city = malloc(AIRPORT_STRING_SIZE);

  // Code to parse `line` into `airport[n]` members.

  // Usually the parsing happens first and if successful, the above allocations occur.

  // If the `LocID` string (and others) need not change then 
  //   use below to allocate a right-sized memory
  //   after parsing instead of allocating to some max size, like above.
  airport[n]->LocID = strdup(LocID_string);

  n++;
}

Later free it all

for (size_t i = 0; i < n; i++) {
  free(airport[i]->LocID);
  free(airport[i]->fieldName);
  free(airport[i]->city);
  free(airport[i]);
}

Detail: Notice the subtle error in the following. It allocates to the size of airport, which is type airPdata **.

Instead, it should allocate to the size of * airport, which is type airPdata *.

Very commonly, object pointers of all types are the same size, yet this same-ness is not specified across all type in C.

Better to allocate to the size of the de-referenced pointer that to a type. It more likely coded right, easier to review and maintain.

// airPdata **airport = malloc(sizeof(airport) * (50+1));
airPdata **airport = malloc(sizeof *airport * (50+1));
0
votes

You are mixing 2 ways of doing this.

A you have a contiguous array of airports

airports -----> ap1 | ap2 | ap3

B You have an array of pointers to airports (not necessarily next to each other in memory

airports --> aptr1 | aptr2 | aptr3
               |        |        |
               v        v        v
              ap1       ap2     ap3

your malloc mixes A and B. if you want A

do

airPdata *airport = malloc(sizeof(airport) * (50+1));

if you want B do

airPdata **airport = malloc(sizeof(airport*) * (50+1));

Then later you will have to allocate an airport object too for each pointer slot.