在 C 中扩展动态 char** 数组时 realloc() 失败

realloc() fail when expanding dynamic char** array in C

我正在编写一个脚本,需要将一个非常大的文件 (110,000L) 中的每一行读取到一个动态数组中(然后它会做一些与我的问题无关的事情)。相关代码如下:

 FILE *orig;
 FILE *dest;
    orig = fopen("../../dicts/mpron/pronDict.txt","r+");
    dest = fopen("../../dicts/editedPronDict.txt","w");

    char **arr = malloc(sizeof(char *)*128);
    int size = 0;
    int capacity = 128;

    char *inputLine = malloc(sizeof(char)*128);
    fgets(inputLine,128,orig);

    while(!feof(orig)){

            arr[size] = malloc(sizeof(char)*128);
            strcpy(arr[size],inputLine);
            size++;

            if(size == capacity){
                    realloc(arr,sizeof(char *)*(capacity*2));
                    capacity*=2;
                    fprintf(stderr,"New size: %i\n",capacity);
            }
    }

这是非常基本的东西,我认为它会 运行 完美。但是,我得到了这个输出:

./organizeMpron
New size: 256
New size: 512
organizeMpron(2088,0x7fff7c53e300) malloc: *** error for object  
0x7fc2aa001200: pointer being realloc'd was not allocated
*** set a breakpoint in malloc_error_break to debug  
Abort trap: 6

所以它在崩溃前容量只增加了一倍。我尝试将数组的初始容量更改为 64,奇怪的是我得到了完全不同的输出:

./organizeMpron
New size: 128
New size: 256
New size: 512
New size: 1024
New size: 2048
New size: 4096
New size: 8192
New size: 16384
New size: 32768
New size: 65536
New size: 131072
Segmentation fault: 11

有人知道这里发生了什么吗?我已经多次以这种方式编写动态集合,但我不知道这段代码在哪里出错。提前谢谢你。

realloc(arr,sizeof(char *)*(capacity*2));

可能会重新分配 arr,但它不会更改 arr 的值,它仍然指向(现已解除分配的)原始块。你可能是说

arr = realloc(arr,sizeof(char *)*(capacity*2));

尽管在重新分配失败的情况下会发生内存泄漏。

详情见realloc manpage


为每一行分配 128 个字节似乎有点傻,除非你相信所有的行都是相同的长度。您可以只分配该行所需的字节数(加上一个终止 NUL)。 (或者您可以将所有行读入一个连续的内存区域,然后使用 strtok 之类的东西来拆分所有换行符并构造您的数组,这会更有效率,但这超出了范围。 )

或者,如果您要为每一行分配一个固定的缓冲区大小,而不管它有多长,那么读入临时缓冲区然后将临时缓冲区复制到数组中是没有意义的。直接读入适当的数组缓冲区即可。

最后,while (!feof(f)) is almost always wrong.