【问题标题】:simple multiple reallocation of double char pointer c [duplicate]双字符指针c的简单多重重新分配[重复]
【发布时间】:2018-07-05 13:56:39
【问题描述】:

我试图在一个更大的程序中动态地重新分配一个双字符指针,我总是得到那个错误“realloc(): invalid next size”,所以我写了一个更小的测试来告诉你我的确切问题:

我的小测试:

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

int main(void){
    char **buf = malloc(sizeof(char*));
    for(int i = 0; i < 20; i++){
        buf[i] = malloc(sizeof(char) * 6);
        strcpy(buf[i], "hallo");
        printf("%s\n", buf[i]);
        if( (realloc(buf, sizeof(char*) * (i+1))) == NULL) exit(-1);
    }

    return 0;
}

这总是在第四次重新分配时崩溃并显示完整的错误消息:

Error in `./myTest': realloc(): invalid next size: 0x0000000001cb2010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f450a4a97e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x834aa)[0x7f450a4b54aa]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x179)[0x7f450a4b6839]
./myTest[0x40069c]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f450a452830]
./myTest[0x400529]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 663159                             
/home/qbongo/BS-PK-2017/10_pk/myTest
00600000-00601000 r--p 00000000 08:01 663159                             
/home/qbongo/BS-PK-2017/10_pk/myTest
00601000-00602000 rw-p 00001000 08:01 663159                             
/home/qbongo/BS-PK-2017/10_pk/myTest
01cb2000-01cd3000 rw-p 00000000 00:00 0                                  [heap]
7f4504000000-7f4504021000 rw-p 00000000 00:00 0 
7f4504021000-7f4508000000 ---p 00000000 00:00 0 
7f450a21c000-7f450a232000 r-xp 00000000 08:01 398530                     
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a232000-7f450a431000 ---p 00016000 08:01 398530                     
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a431000-7f450a432000 rw-p 00015000 08:01 398530                     
/lib/x86_64-linux-gnu/libgcc_s.so.1
7f450a432000-7f450a5f2000 r-xp 00000000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a5f2000-7f450a7f2000 ---p 001c0000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f2000-7f450a7f6000 r--p 001c0000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f6000-7f450a7f8000 rw-p 001c4000 08:01 394742                     
/lib/x86_64-linux-gnu/libc-2.23.so
7f450a7f8000-7f450a7fc000 rw-p 00000000 00:00 0 
7f450a7fc000-7f450a822000 r-xp 00000000 08:01 393312                     
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa07000-7f450aa0a000 rw-p 00000000 00:00 0 
7f450aa20000-7f450aa21000 rw-p 00000000 00:00 0 
7f450aa21000-7f450aa22000 r--p 00025000 08:01 393312                     
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa22000-7f450aa23000 rw-p 00026000 08:01 393312                     
/lib/x86_64-linux-gnu/ld-2.23.so
7f450aa23000-7f450aa24000 rw-p 00000000 00:00 0 
7ffcc108f000-7ffcc10b0000 rw-p 00000000 00:00 0                          [stack]
7ffcc1149000-7ffcc114b000 r--p 00000000 00:00 0                          [vvar]
7ffcc114b000-7ffcc114d000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  
[vsyscall]
Aborted (core dumped)

【问题讨论】:

    标签: c pointers char realloc


    【解决方案1】:

    通过调用char **buf = malloc(sizeof(char*));,您只分配了一个指针,而不是它们的数组。

    const size_t items_count = 20;
    char **buf = malloc(sizeof(char*) * items_count);
    for(int i = 0; i < items_count; i++){
        buf[i] = malloc(sizeof(char) * 6); // now we won't access array out of bounds here
    // no need to realloc
    

    【讨论】:

    • 但他在每次迭代中重新分配。我不认为这段代码是实际代码,而只是一个示例,用于显示 realloc 的迭代失败。
    • @Groo Realoc 代码是错误的(它将重新分配相同数量的字节),并且在预先知道数组大小时毫无意义。
    • 是的,我想用 if( (realloc(buf, sizeof(char*) * (i+1))) == NULL) exit(- 1);
    • @Qbongo “调用数组的下一个指针”是什么意思?
    • @Groo 你是完全正确的,它只是指出问题的一个例子
    【解决方案2】:

    应该是这样的:

    buf = realloc(buf, sizeof(char*) * (i+2));
    
    1. 您的代码只是丢弃了realloc 的结果。
    2. 如果您在迭代结束时分配(i+2),则需要分配。

    我假设这不是您的实际代码,但将realloc 移动到循环顶部(检查first example for realloc on this page)会更有意义,例如:

    for(int i = 0; i < 20; i++)
    {
        buf = realloc(buf, sizeof(char*) * (i+1));
        if (buf == NULL)
            exit(-1);
    
        ...
    }
    

    (更新)

    根据下面@coderredoc 的cmets,虽然exit 将释放与进程相关的所有内存,但请记住,良好的编程习惯是释放先前分配的指针,以防realloc 失败:

    char **buf = malloc(sizeof(char*));
    for (int i = 0; i < 20; i++)
    {
        // try to realloc
        {
            char ** larger = realloc(buf, sizeof(char*) * (i + 1));
            if (larger) 
            {
                buf = larger;
            }
            else 
            {
                // realloc failed, we might need to free individual items
                // if we are not going to use them anymore
                for (int k = 0; k < (i - 1); k++) free(buf[k]);
    
                // we should free previous buff also
                free(buff);
    
                // we can exit, or break the loop, or whatever
                exit(-1);
            }
        }
    
        // do stuff here
        ...
    }
    

    【讨论】:

    • @coderredoc:我还是用你的 cmets 更新了答案,有人会发现这些细节很有用,谢谢!
    【解决方案3】:

    我在您的代码中看到 2 个错误。

    1. 您没有将realloc 返回的新地址存储在buf 中。当所需的新空间不可用时,realloc 会在内存中的其他位置分配新空间。

    2. 你的循环从i = 0开始,因此当你第一次到达realloc时,你需要分配两个元素:i+2而不是i+1

    【讨论】:

    • 非常感谢,这解决了问题
    猜你喜欢
    • 2016-10-09
    • 1970-01-01
    • 2021-04-03
    • 2013-01-07
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    相关资源
    最近更新 更多