简体   繁体   中英

Dynamic Array: error free(): invalid next size (fast), Segmentation fault (core dumped)

So I was trying to pormpt the user to type in a number, and then store that value in a dynamic array. Here is the code first:

#include <stdio.h>
#include <stdlib.h>

//dynamically grow the array 
void growArray(int *arr, int *size){
    //double the size of the array
    printf("Resizing array\n");
    int *temp = malloc( *size * 2 * sizeof(int)); 
    printf("Malloc was succesfuly\n");
    int i; 
    for (i = 0; i < *size; i++)
        temp[i] = arr[i]; 

    printf("About to free arr\n");
    printf("arr: %p", arr); 
    printf("temp: %p", temp);
    free(arr);
    arr = malloc( *size * 2 * sizeof(int)); 
    printf("About to change value to arr\n");
    arr = temp; 
    free(temp);
    printf("About to change the value of size\n");
    *size *= 2; 
    printf("New size: %d\n", *size);
}


int main(){

    int *dynamicArr; 
    int *size; 
    *size = 1; 
    dynamicArr = (int*) malloc(sizeof(int));

    int value, i;
    i = 0; 
    do{
        printf("\nPlease enter in a int value: ");
        scanf("%d", &value); 

        //check if the array needs to be resizesd;
        printf("Checking if size if sufficient\n");
        if (i >= *size)
            growArray(dynamicArr, size);

        if (value != -999){
            printf("Adding value to the array\n");
            dynamicArr[i] = value;
            i ++; 
        }
    }while(value != -999); 

    for (i = 0; i < *size; i++){
        printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
    }

    return 0; 
}

As you can see, I have a bunch of print statements, that I so I can see at what point my program is at, and what it is current doing. So, the program initially works. I am able to add in 8 values successfully (and resize the array 3 times, going from size 1 to size 8). But when I add in my 9 value, it has to resize the array, in which the method growArray() is called. But, for some reason I get the following error:

*** Error in `./a.out': free(): invalid next size (fast): 0x0000000000e69010 ***
Segmentation fault (core dumped)

Before the error, the printf("About to free arr") works, but printf("arr: %p", arr); isn't called.

I have no idea why this is happening, some help would be much appreciated.

You code should probably look more like this:

#include <stdio.h>
#include <stdlib.h>

int main() {
    int size = 1;
    int *dynamicArr = malloc(size * sizeof(*dynamicArr));

    int idx = 0;
    while (1) {
        int value;
        printf("\nPlease enter in a int value: ");
        scanf("%d", &value);

        if (value == -999) {
            break;
        }

        //check if the array needs to be resizesd
        printf("Checking if size if sufficient\n");
        if (idx >= size) {
            size *= 2;
            dynamicArr = realloc(dynamicArr, size * sizeof(*dynamicArr));
        }

        printf("Adding value to the array\n");
        dynamicArr[idx++] = value;
    }

    int i;
    for (i = 0; i < idx; i++) {
        printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
    }

    free(dynamicArr);
    return 0; 
}

Or if you want to stick with your implementation:

#include <stdio.h>
#include <stdlib.h>

//dynamically grow the array 
void growArray(int **arr, int *size){
    //double the size of the array
    printf("Resizing array\n");
    int *temp = malloc( *size * 2 * sizeof(int)); 
    printf("Malloc was succesfuly\n");
    int i;
    for (i = 0; i < *size; i++)
        temp[i] = (*arr)[i];

    printf("About to free arr\n");
    printf("arr: %p\n", *arr); 
    printf("temp: %p\n", temp);
    free(*arr);
    printf("About to change value to arr\n");
    *arr = temp;
    printf("About to change the value of size\n");
    *size *= 2;
    printf("New size: %d\n", *size);
}


int main() {
    int size = 1;
    int *dynamicArr = malloc(size * sizeof(*dynamicArr));

    int idx = 0;
    while (1) {
        int value;
        printf("\nPlease enter in a int value: ");
        scanf("%d", &value);

        if (value == -999) {
            break;
        }

        //check if the array needs to be resizesd;
        printf("Checking if size if sufficient\n");
        if (idx >= size) {
            growArray(&dynamicArr, &size);
        }

        printf("Adding value to the array\n");
        dynamicArr[idx++] = value;
    }

    int i;
    for (i = 0; i < idx; i++){
        printf("Value of dynamicArr[%d]: %d\n", i, dynamicArr[i]);
    }

    free(dynamicArr);
    return 0; 
}

BTW, you can use memcpy to copy the whole existing array to the temp array.

There are a couple of problems in your original code.

(a) The parameter arr is passed to growArray by value, so your assignments arr = malloc(...) and arr = temp are not updating the variable referenced in main() only the copy that is local to growArray . On the other hand, when you call free(arr) you are freeing the buffer pointed to by the variable dynamicArr in main() . This is the immediate cause of your segfault.

(b) When you assign arr = temp then free(temp); you leak the buffer you malloc() ed just above, then free the buffer you assigned arr to point to (leaving it dangling).

void growArray(int *arr, int *size){

When entering growArray , arr points to a buffer, A

    ...
    int *temp = malloc( *size * 2 * sizeof(int));

temp is initialized to point to a new buffer, B

    ...
    free(arr);

the original buffer, A, is freed. The local variable arr is now a dangling pointer, as is whatever pointer the caller holds that was passed into this routine by value.

    arr = malloc( *size * 2 * sizeof(int)); 

arr is set to a freshly allocated buffer, C.

    ...
    arr = temp; 

arr is set to alias temp , pointing to the buffer B. The buffer C is leaked.

    free(temp);

Buffer B, pointed to by both temp and arr is freed. They are both now dangling pointers. When arr is later

    ...
}

Both tmp and arr go out of scope. The buffers B and C are leaked.

int main(){

    int *dynamicArr; 
    int *size; 
    *size = 1; 
    dynamicArr = (int*) malloc(sizeof(int));

dynamicArr points to a malloced buffer ... do{ ... if(...){ growArray(dynamicArr, size); ... }

The first time this if condition passes, the value of dynamicArr is passed as the argument arr to growArray. growArray frees the buffer it points to and then allocs and leaks some memory without affecting the local value of dynamicArr . dynamicArr is now a dangling pointer.

        if (value != -999){
            ...
            dynamicArr[i] = value;

And then this accesses the dangling pointer and segfaults.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM