2

I have a pointer to several structures that have been allocated memory via:

STRUCTNAME *ptr;
ptr = (STRUCTNAME *)malloc(sizeof(STRUCTNAME)*numberOfStructs);

The structures are accessed via a offset like so:

(ptr + i)->field;

The structures have 2 fields that are character pointers as follows:

typedef struct
{
    char *first;
    char *second;
}STUCTNAME;

These fields are allocated memory as follows:

(ptr + i)->first = (char *)malloc(strlen(buffer));

This appears to work but when I try to free the pointers within the structures I get a segmentation fault 11 when I do this:

free((prt + i)->first);

Help?

Notes: buffer is a character array. Offsetting a pointer by a integer should increment the pointer by the size of what it is pointing to times the integer correct?

Here is a link to my full source code. I have not written some of the functions and I am not using the freeAllpointers and printAll yet. https://drive.google.com/file/d/0B6UPDg-HHAHfdjhUSU95aEVBb0U/edit?usp=sharing

OH! Thanks everyone! Have a happy Thanksgiving! =D (If you're into that kinda stuff)

MacK
  • 433
  • 4
  • 7
  • 4
    First of all, [do not ever. I repeat, **do not ever** cast the return value of `malloc()`!](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc/605858#605858) –  Nov 28 '13 at 18:57
  • But anyway, you are not supposed to free the pointers to the individual members of the array. A pointer is only to be `free()`d when it was `malloc()`ated (or `calloc()`ated or `realloc()`ated), which is only the pointer to the *very first element.* –  Nov 28 '13 at 18:58
  • 2
    How about `ptr[i].first`? Looks much nicer. – Kninnug Nov 28 '13 at 19:00
  • 1
    Have the struct pointers been freed before freeing the char pointers? ;) – XORcist Nov 28 '13 at 19:01
  • @H2CO3: I believe that is the case. The STRUCTNAME* is malloc'ed but also STRUCTNAME::first is malloc'ed, so that pointer needs to be freed as well. – Pat Nov 28 '13 at 19:02
  • @XORcist No, that's not the problem, read the question again. –  Nov 28 '13 at 19:05
  • It's quite possible that some memory corruption elsewhere is confusing things. Try running your program through `valgrind`. – creichen Nov 28 '13 at 19:06
  • 1
    `(char *)malloc(strlen(buffer));` is suspicious. Did you copy `buffer` with `strcpy` afterwards ? You're trashing memory if you are- since there's no room for the nul terminator. Use `malloc(strlen(buffer)+1)` – nos Nov 28 '13 at 19:27

1 Answers1

1
  • In case, you don't initialize all those members in that piece of code, you're not showing us:
    Allocate the struct storage (STRUCTNAME*) with calloc(), so that all allocated memory, namely firstand second are zero at the beginning. Passing NULL to free() will result in a no-op. Passing any wild (garbage) pointer to free() may cause a segmentation fault.
  • To detect a double-free, set ptr[i].first = NULL; after free(ptr[i].first); as a defensive measure for testing.

Notes: buffer is a character array. Offsetting a pointer by a integer should increment the pointer by the size of what it is pointing to times the integer correct?

Yes, except for void* on those compilers, which don't define sizeof(void), which is defined to have undefined behavior, to a value > 0: What is the size of void?

Edit:

void makeReviews(FILE *input, REVIEW *rPtr, int numReviews) <-- This does NOT return the new value of rPtr. In main(), it will remain NULL. Do something like this:

REVIEW* makeReviews(FILE *input, int numReviews);
//...
int main(){
    //...
    rPtr = makeReviews(input,numReviews);
    //...
}

or

void makeReviews(FILE** input,REVIEW** rPtrPtr,int numReviews){
    REVIEW* rPtr = *rPtrPtr;
    //...
    *rPtrPtr = rPtr;
}
//...
int main(){
    //...
    makeReviews(input,&rPtr,numReviews);
    //...
}

fgets(cNumReviews, sizeof(cNumReviews), input); <-- Perhaps, you could use something like fscanf().

Community
  • 1
  • 1
Sam
  • 7,778
  • 1
  • 23
  • 49
  • I believe fgets works fine since when I print the value of the fields inside of makeReviews the output is as expected. I will try doing what you said with the return type of makeReviews. Thanks again. – MacK Nov 28 '13 at 19:58
  • @Mac: You're welcome. I suggested `fscanf()` as a possible shortcut, not as a fix. – Sam Nov 28 '13 at 20:02
  • Wow apparently I do not understand passing pointers by reference? That did the trick. Thanks a lot mate. – MacK Nov 28 '13 at 20:02
  • You're welcome. You cannot pass by reference in C. What you can do is passing a pointer to a pointer (see edit). – Sam Nov 28 '13 at 20:04
  • Oh and yes I see what you mean with `fscanf()`. I misunderstood. – MacK Nov 28 '13 at 20:12