堆栈转储当使用malloc时

6pp0gazn  于 2023-03-01  发布在  其他
关注(0)|答案(3)|浏览(176)

这是我的节目单

#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语句产生了一些错误。问题是什么?

eufgjt7s

eufgjt7s1#

您没有释放分配的指针,因为像pt[0] = "Earth";这样的语句会用硬编码字符串“Earth”的地址覆盖pt[0]中的地址。
因此,当free在您的代码中运行时,它会尝试释放错误的内存地址。
在这一点上,要么free被编码以检查这种可能性,它故意使程序崩溃,而不是做坏事,要么free试图信任地做基于您给它的地址不应该做的事情,并被操作系统的现代安全功能杀死(例如,当程序运行时,现代操作系统会将硬编码字符串加载到标记为只读的内存页中,因此如果程序试图写入那里,它会得到一个默认致命信号)。
为什么free在给定一个错误地址时会做一些不应该做的事情?因为传统上编写内存分配器的一种方法是分配比您要求的稍大的块,并将该分配的元数据存储在该空间的前面,和/或在您释放该空间后将重用该内存所需的元数据写入该空间。在这样的分配器中,每一个free都会导致一些内存在你给它的地址附近被覆盖。这种设计已经导致了代码中的许多bug和可利用的安全漏洞,但是最近我检查了它在一些C实现中仍然存在。
现在谈谈你的大目标:
你似乎期待=将字符从一个位置复制到另一个位置。这在来自高级语言时是有意义的,但C没有这样的语法糖。相反,在C中,内存地址(“指针”)上的=复制内存地址。
这可能也不明显,但在C语言中,字符串常量表达式的工作方式与指针类似--表达式"Earth"的类型实际上是char *
无论如何,由于其他函数有指针输出,您可以使用strcpy这样的函数将“Earth”中的字符复制到新分配的存储空间中。您也可以使用循环自己复制字符,但在大多数情况下不建议这样做,因为标准库实现:以C开发人员可以立即理解的方式表达您的意思;可以被优化以比单纯的逐字节循环执行得更好,并且;可能被编译器的优化器传递所理解。

a0zr77ik

a0zr77ik2#

很可能是程序试图释放已经释放的内存或者不是使用malloc函数动态分配的内存,要解决这个问题,可以使用strcpy()这样的方法将字符串常量的内容复制到malloc()分配的内存中。

s3fp2yjn

s3fp2yjn3#

由于常量字符串存储在程序数据段只读竞技场,您不能直接释放它!!使用strcpy将str复制到您分配的内存中
理解应用程序二进制段在c中是非常重要的,有这些段:
堆栈堆BSS(未初始化数据段)数据(已初始化只读和初始化读写区)代码(包含可执行指令)

相关问题