动态数组:无错误():下一个大小无效(快),分段错误(核心转储)

时间:2017-09-09 20:45:30

标签: c arrays

所以我试图让用户输入一个数字,然后将该值存储在动态数组中。首先是代码:

#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; 
}

正如你所看到的,我有一堆打印语句,我可以看到我的程序在什么时候,以及它当前在做什么。所以,该计划最初是有效的。我能够成功添加8个值(并将数组调整大小3次,从大小1到大小8)。但是当我添加我的9值时,它必须调整数组的大小,其中调用方法growArray()。但是,由于某种原因,我收到以下错误:

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

在出错之前,printf(“关于自由arr”)有效,但是printf(“arr:%p”,arr);不叫。

我不知道为什么会这样,一些帮助会非常感激。

2 个答案:

答案 0 :(得分:2)

您的代码应该看起来更像这样:

#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; 
}

或者如果您想坚持实施:

#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; 
}

顺便说一句,您可以使用memcpy将整个现有数组复制到临时数组。

答案 1 :(得分:1)

原始代码中存在一些问题。

(a)参数arr按值传递给growArray,因此您的作业arr = malloc(...)arr = temp不会更新main()中引用的变量只有growArray本地的副本。另一方面,当您调用free(arr)时,您正在释放dynamicArr中变量main()指向的缓冲区。这是您的段错误的直接原因。

(b)当您分配arr = temp然后free(temp);时,您泄漏了malloc()刚刚上方的缓冲区,然后释放您指定的缓冲区arr指向(离开)它摇摇晃晃)。

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

输入growArray时,arr指向缓冲区,A

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

temp被初始化为指向新缓冲区B

    ...
    free(arr);

原始缓冲区A被释放。局部变量arr现在是一个悬空指针,就像调用者按照值传递到此例程中的指针一样。

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

arr设置为新分配的缓冲区C。

    ...
    arr = temp; 

arr设置为别名temp,指向缓冲区B.缓冲区C泄露。

    free(temp);

释放temparr指向的缓冲区B.他们现在都是悬挂指针。 arr稍后

    ...
}

tmparr都超出了范围。缓冲区B和C泄漏。

int main(){

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

dynamicArr指向malloced缓冲区         ...         做{             ...             如果(...){                 growArray(dynamicArr,size);                 ...             }

第一次if条件通过时,dynamicArr的值作为参数arr传递给growArray。 growArray释放它指向的缓冲区,然后分配和泄漏一些内存而不影响dynamicArr的本地值。 dynamicArr现在是一个悬垂的指针。

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

然后这会访问悬空指针和段错误。