You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何对malloc分配的字符串调用realloc却失效?

问题:realloc调用返回NULL且Valgrind报无效内存操作错误

我为了理解malloc的工作机制,写了个程序观察数组扩容后的内存地址变化,但调用realloc时返回NULL,Valgrind还报了错误。

原代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char* buff;
    buff = malloc(10);
    buff = "hi";
    printf("%c\n", buff[0]);
    printf("%p\n", &buff[0]);

   if (realloc(buff, (size_t) 20) == NULL){
       printf("no\n");
       exit(1);
   }
    
    printf("%p\n", &buff[0]);
    
    return 0;
}

Valgrind运行结果:

valgrind ./test
==3421== Memcheck, a memory error detector
==3421== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==3421== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==3421== Command: ./test
==3421==
h
0x400734
==3421== Invalid free() / delete / delete[] / realloc()
==3421==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3421==    by 0x400673: main (in /home/puf311/cs3733/practice/test)
==3421==  Address 0x400734 is not stack'd, malloc'd or (recently) free'd
==3421==
no==3421==
==3421== HEAP SUMMARY:
==3421==     in use at exit: 10 bytes in 1 blocks
==3421==   total heap usage: 2 allocs, 1 frees, 15 bytes allocated
==3421==
==3421== LEAK SUMMARY:
==3421==    definitely lost: 10 bytes in 1 blocks
==3421==    indirectly lost: 0 bytes in 0 blocks
==3421==      possibly lost: 0 bytes in 0 blocks
==3421==    still reachable: 0 bytes in 0 blocks
==3421==         suppressed: 0 bytes in 0 blocks
==3421== Rerun with --leak-check=full to see details of leaked memory
==3421==
==3421== For counts of detected and suppressed errors, rerun with: -v
==3421== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

我原以为字符串是malloc分配的且没提前free,为啥会出问题?


问题分析:

核心错误在buff = "hi";这行代码:

  • 你先用malloc(10)给buff分配了一块堆内存,此时buff指向堆里的地址。
  • 但紧接着buff = "hi";把buff的指针值改成了字符串常量"hi"的地址——这个地址属于程序的只读数据段,根本不是malloc分配的堆内存。
  • 后面调用realloc(buff, 20)时,传入的是只读数据段的地址,不是malloc返回的有效堆指针,所以Valgrind报错“地址不是栈、malloc分配或最近free的”,realloc自然返回NULL。
  • 另外,原来malloc的10字节堆内存因为指针被覆盖,再也无法访问,造成了内存泄漏(对应Valgrind里的“definitely lost:10 bytes”)。

修正后的代码:

要把字符串复制到malloc分配的堆内存里,而不是直接赋值指针,同时还要正确保存realloc的返回值(因为realloc可能返回新的地址):

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char* buff;
    buff = malloc(10);
    if (buff == NULL) { // 先检查malloc是否成功
        printf("malloc failed\n");
        exit(1);
    }
    strcpy(buff, "hi"); // 把字符串复制到堆内存中,而不是修改指针
    printf("%c\n", buff[0]);
    printf("%p\n", &buff[0]);

    char* temp = realloc(buff, 20); // 用临时变量保存realloc返回值,避免原指针丢失
    if (temp == NULL){
        printf("realloc failed\n");
        free(buff); // 原内存还在,要释放避免泄漏
        exit(1);
    }
    buff = temp; // 重新赋值buff到新的内存地址
    
    printf("%p\n", &buff[0]);
    
    free(buff); // 最后释放内存
    return 0;
}

内容的提问来源于stack exchange,提问作者gwynb2001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:45:24