这是我的节目单
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char * pt[3];
size_t size = sizeof(char);
pt[0] = (char *) malloc(60 * size);
pt[1] = (char *) malloc(60 * size);
pt[2] = (char *) malloc(60 * size);
pt[0] = "Earth";
puts(pt[0]);
puts("===================================\n");
pt[1] = "University";
puts(pt[1]);
puts("===================================\n");
pt[2] = "Things are very interesting!";
puts(pt[2]);
puts("===================================\n");
for (int i = 0; i < 3; i++)
{
free(pt[i]);
}
return 0;
}
现在,程序按预期打印,但在最后有一些错误cygwin_exception::open_stackdumpfile: Dumping stack trace to a.exe.stackdump
我试着放一些printf语句,我发现free
语句产生了一些错误。问题是什么?
3条答案
按热度按时间eufgjt7s1#
您没有释放分配的指针,因为像
pt[0] = "Earth";
这样的语句会用硬编码字符串“Earth”的地址覆盖pt[0]
中的地址。因此,当
free
在您的代码中运行时,它会尝试释放错误的内存地址。在这一点上,要么
free
被编码以检查这种可能性,它故意使程序崩溃,而不是做坏事,要么free
试图信任地做基于您给它的地址不应该做的事情,并被操作系统的现代安全功能杀死(例如,当程序运行时,现代操作系统会将硬编码字符串加载到标记为只读的内存页中,因此如果程序试图写入那里,它会得到一个默认致命信号)。为什么
free
在给定一个错误地址时会做一些不应该做的事情?因为传统上编写内存分配器的一种方法是分配比您要求的稍大的块,并将该分配的元数据存储在该空间的前面,和/或在您释放该空间后将重用该内存所需的元数据写入该空间。在这样的分配器中,每一个free
都会导致一些内存在你给它的地址附近被覆盖。这种设计已经导致了代码中的许多bug和可利用的安全漏洞,但是最近我检查了它在一些C实现中仍然存在。现在谈谈你的大目标:
你似乎期待
=
将字符从一个位置复制到另一个位置。这在来自高级语言时是有意义的,但C没有这样的语法糖。相反,在C中,内存地址(“指针”)上的=
复制内存地址。这可能也不明显,但在C语言中,字符串常量表达式的工作方式与指针类似--表达式
"Earth"
的类型实际上是char *
。无论如何,由于其他函数有指针输出,您可以使用
strcpy
这样的函数将“Earth”中的字符复制到新分配的存储空间中。您也可以使用循环自己复制字符,但在大多数情况下不建议这样做,因为标准库实现:以C开发人员可以立即理解的方式表达您的意思;可以被优化以比单纯的逐字节循环执行得更好,并且;可能被编译器的优化器传递所理解。a0zr77ik2#
很可能是程序试图释放已经释放的内存或者不是使用malloc函数动态分配的内存,要解决这个问题,可以使用strcpy()这样的方法将字符串常量的内容复制到malloc()分配的内存中。
s3fp2yjn3#
由于常量字符串存储在程序数据段只读竞技场,您不能直接释放它!!使用strcpy将str复制到您分配的内存中
理解应用程序二进制段在c中是非常重要的,有这些段:
堆栈堆BSS(未初始化数据段)数据(已初始化只读和初始化读写区)代码(包含可执行指令)