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
相关产品推荐
相关产品推荐

