Search code examples
cpointersreallocdouble-pointer

Segmentation fault after realloc in function


I have created this code to test one error, that I get in my main code, and it shares the same problem. I'm always getting either segmentation fault or corrupted data (zeros or strange numbers).

Here is the code:

int *p=NULL;
int func (int **point);

int main() {
    int num = 5647;
    p = malloc(sizeof(int)*2);
    p[0] = num;
    p[1]= 657;
    printf("%d\n", p[0]);
    printf("%d\n", p[1]);
    func(&p);
    printf("%d\n", p[0]);
    printf("%d\n", p[1]);
    printf("%d\n", p[2]);
    printf("%d\n", p[3]);
    return 0;
}

int func (int **point){
    *point = realloc(*point,sizeof(int)*4);
    if (*point==NULL){
        printf("\n abort \n");
        exit(0);
    }
    *point[0] = 867;
    *point[1]= 777;
    *point[2] = 67;
    *point[3]= 77;
}  

I'm getting the segmentation fault on the *point[1]=777;. If I'm trying to do like point[1]=777; I'm getting wrong data. With any changes in int func (int **point); or func(&p); I'm getting segmentation fault on realloc.

Please advise, I have read information about double pointers and tried to follow all solutions I found, but every time I'm getting this error.


Solution

  • Your problem is operator precedence, change *point[0] to (*point)[0] and so forth.

    What you have right now is *(point[0]). You treat a pointer to a single element as a pointer to multiple consecutive elements and then dereference some indeterminate value as an address. This results in undefined behavior, which luckily for you manifests as a crash.

    After the change you first dereference point and then use that address to index into consecutive elements you allocated.

    Two suggestions for improvement:

    Don't assign the result of realloc directly to *point. If the call fails, then you leak the original memory. Assign it to a temporary first for verification.

    Also, try not to repeat types. Instead of sizeof(int) try for sizeof(**point), i.e whatever the output buffer is supposed to point at. That way you won't have silent errors in your code if you change the type from int to something else.

    void *point_check = realloc(*point,sizeof(**point)*4);
    if (point_check == NULL){
        printf("\n abort \n");
        exit(0); // If this ever returns instead of exit, `*point` will not leak
    }
    *point = point_check;