realloc():重新分配时为下一个大小无效,以便为char*上的strcat腾出空间

PUG*_*PUG 13 c string malloc realloc strcat

我在以下代码中收到无效的内存错误:

printf(" %s\n","FINE 5");
printf("%s LENGTH IS: %d\n","FINE 6",strlen(": "));
buffer = (char *)realloc(buffer, strlen(buffer)* sizeof(char) + (strlen(": ")+1)* sizeof(char));
printf(" %s\n","FINE 7");
strcat(buffer, ": \0");
Run Code Online (Sandbox Code Playgroud)

输出:

FINE 5
FINE 6 LENGTH IS:
检测到 2 *glibc* ./auto:realloc():下一个大小无效:0x08cd72e0***======= Backtrace:=========/lib/tls /i686/cmov/libc.so.6(+0x6b591)[0x6dd591]

这里需要注意的Fine 7是从未打印过.每次运行时无效的下一个大小错误位于同一位置.

发现这种相关性

Dav*_*nan 12

发生此错误是因为代码的某些其他部分已损坏堆.如果没有看到其余代码,我们无法告诉您错误是什么.

FINE 7未打印的事实告诉您realloc失败.并且该失败必须是因为buffer在执行的早期由于堆损坏而无效.


正交你的实际问题,sizeof(char)1由定义是很有意义从代码中删除它.

  • 如果没有堆损坏,那么`realloc` 就会成功。缓冲区可以正常打印,但它是已损坏的内存块的元数据。分配内存时,还会有一个由分配器在内部使用的头块。那就是腐败。无论如何,我已经多次表达了我的观点。 (2认同)

Gre*_*ndl 8

正如David Heffernan指出的那样,你的根问题必须是代码中其他地方的一个狂野指针.

不过,在这段代码中还有其他一些值得考虑的事情:

  1. 新大小表达式中不需要sizeof(char),因为sizeof(char)根据定义为1.

  2. 永远不要将realloc的返回值直接分配回指向要重新分配的缓冲区的唯一指针.如果realloc在错误上返回NULL,您将丢失指向旧缓冲区的指针,并获得自己的内存泄漏.你总是想做相应的:

    footype *p = realloc(oldbuff, newsize);
    if (!p) {
        handle_error();
    } else {
        oldbuff = p;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在C中,void*将在赋值时自动转换为正确的类型,不需要强制转换.此外,通过强制转换,在某些情况下,当您忘记包含相关函数的声明时,您将不会收到有用的错误消息.

  4. 字符串文字包含隐含的nul终止符.你想说:

    strcat(buffer,":");

从好的方面来说,strcat会在第一个nul字符处停止,所以在这种情况下没有坏处.