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

C语言calloc分配内存后赋值字符串再free报错原因咨询

问题根因

报错的核心原因是你修改了指针变量本身存储的地址值,导致传给free的不是动态申请的堆内存地址,具体执行逻辑拆解如下:

  • 执行test = (char *)calloc(15, sizeof(char));时,程序在堆区申请15字节内存,将这块内存的首地址存入指针变量test,此时test指向合法的、可被free释放的堆内存。
  • 取消注释执行test = "Wurstbrot";时,字符串字面量"Wurstbrot"存储在程序的只读常量区,这行代码的作用是把常量区中这个字符串的首地址直接赋值给test,直接覆盖了之前存储的calloc返回的堆地址——你之前申请的那块堆内存从此失去了引用,已经发生了内存泄漏。
  • 执行free(test)时,传入的参数是常量区字符串的地址,而非堆内存地址。free仅能释放malloc/calloc/realloc等动态内存分配函数返回的堆地址,常量区内存不属于堆管理器的分配范围,自然会触发「指针指向的内存未被分配」的报错。
为什么移除free就不报错

移除free调用后,程序只是把指针指向了常量区的字符串,没有触发堆管理器对非法地址的校验逻辑,所以不会立刻崩溃,但之前calloc申请的堆内存因为引用丢失始终没有被释放,依然存在内存泄漏问题,只是程序运行周期短,进程退出后系统会回收所有内存,你感知不到异常而已。

正确写法

如果要把字符串存入你申请的堆内存,不能直接给指针赋值(这会修改指针指向),需要用字符串拷贝函数把内容复制到堆内存空间里,保证test始终保存calloc返回的堆地址:

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

int main()
{
    char    *test;

    test = (char *)calloc(15, sizeof(char));
    strcpy(test, "Wurstbrot"); // 拷贝字符串内容到堆内存,不修改test的指向
    free(test); // 传入合法堆地址,释放正常
    return 0;
}

补充提示:字符串字面量所在的常量区内存是只读的,如果你直接对test = "Wurstbrot"后的test指针做写入操作(比如test[0] = 'w'),还会触发段错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:12:19