C realloc(): invalid next size错误

C realloc(): invalid next size

问题代码

#include 
#include 

int *getNumber();
void printfList(int const* list);

int main(){
    int *list = getNumber();
    printfList(list);
    free(list);
    return 0;
}

int *getNumber(){
    int *list = (int *)calloc(1, sizeof(int));
    int count = 0;
    *list = count;

    int num = 0;
    while (scanf("%d", &num) == 1){
        list[0] = ++count;
        list = realloc(list, sizeof(int) * count);
        list[count] = num;
    }
    return list;
}

void printfList(int const* list){
    int count = *list++;
    for (int i=0;i < count;i++)
        printf("%d,", *list++);
    printf("\n");
}

这个代码大致的工作是从stdin中读取数字,并且写入到数组中,其中数组的第一个元素记录的是读取数字的个数。
出现有问题的代码位于此处:list = realloc(list, sizeof(int) * count);

问题分析

在经过一番折腾之后,关于出现list = realloc(list, sizeof(int) * count);错误的原因我在网上大致了解了,主要有如下:

  • 计算长度的方式不对,比如:
char *tmp = calloc(1, sizeof(char);
// 经过一系列操作
tmp = realloc(tmp, sizeof(char *)*10);

两次计算长度使用的sizeof中的类型不同,虽然这不一定是代码错误,但通常他不是我们想要的结果。

  • 越界读取,这通常不仅会导致realloc有问题,还可能会导致free等操作有问题。

我还看到过另外一个原因,就是realloc申请的内存比原来的内存小。我没有求证过这个错误,但据我所知,realloc不仅可以扩大内存,还可以缩小内存的。

解决问题

我的问题非常奇怪,因为在我输入大约6个数字的时候,调用realloc是没有问题的,但是多于6个数字就会出现问题了。
最后仔细检查代码,发现list = realloc(list, sizeof(int) * count);中,count指的不是数组的长度,而是读取数字的个数。因为数组的首位保存的是数字读取的个数,所以数组的总长度应该是读取数字的个数并且加一。
我把代码换成list = realloc(list, sizeof(int) * (count + 1));就成功执行了。
看来,我的问题是属于上面问题分析中的第二种问题。
至于为什么在输入小于6个数字的时候没有报错,估计是因为我虽然越界读取,但没有破坏到其他资源,所以没有出错吧。

你可能感兴趣的:(C)