英文:
stack dump while using malloc
问题
这是我的程序:
#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
语句正在创建一些错误。问题可能是什么?
英文:
Here is my program
#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;
}
Now, program prints as expected. But there is some error at the end
cygwin_exception::open_stackdumpfile: Dumping stack trace to a.exe.stackdump
I tried to put some printf statements and I found that free
statement is creating some error. What could be the problem ?
答案1
得分: 1
你没有释放你分配的相同指针,因为像pt[0] = "Earth";
这样的语句会覆盖pt[0]
中的地址,用硬编码的字符串"Earth"的地址进行覆盖。
所以当你的代码中运行free
时,它尝试释放错误的内存地址。
此时,要么free
被编码为检查这种可能性,并故意崩溃程序而不是执行不好的操作,要么free
试图信任地根据你提供的地址执行它不应该执行的操作,并被操作系统的现代安全功能杀掉(例如,当程序运行时,现代操作系统将将硬编码的字符串加载到标记为只读的内存页中,因此如果尝试在那里写入,程序会收到致命的默认信号)。
为什么free
会在给定错误的地址时执行它不应该执行的操作呢?因为传统上内存分配器的一种写法是分配比你要求的稍大的块,并在该空间的前面存储该分配所需的元数据,和/或在你释放它后将用于重用该内存的元数据写入该空间。在这种分配器中,每次free
都会导致在你提供的地址附近覆盖一些内存。这种设计已经导致了代码中许多错误和可利用的安全漏洞,但据我所知,它仍然存在于一些C实现中。
现在关于你更大的目标:
你似乎期望=
能够从一个位置复制字符到另一个位置。从更高级的语言转过来时,这可能是有道理的,但是C没有这种语法糖。在C中,对内存地址("指针")使用=
会复制内存地址。
也可能不太明显,但在C中,字符串文字表达式主要像指针一样工作 - 表达式"Earth"
的类型实际上是char *
。
无论如何,正如其他人指出的,你可以使用strcpy
之类的函数将字符从"Earth"复制到新分配的存储空间。你也可以使用循环自己复制字符,但在大多数情况下不建议这样做,因为标准库的实现:以一种C开发人员可以立即理解的方式表达了你的意思;可能经过优化,以比天真的逐字节循环更好的性能执行;可能会被你的编译器的优化器通行。
英文:
You're not freeing the same pointers you allocated, because a statement like pt[0] = "Earth";
is overwriting the address in pt[0]
with the address of the hard-coded string "Earth".
So by the time that free
runs in your code, it tries to deallocate the wrong memory address.
At that point, either free
was coded to check for this possibility and it deliberately crashed the program instead of doing bad things, or free
tried to trustingly do things that it wasn't supposed to based on the address you gave it, and got killed by modern safety features of the OS (for example, when a program runs, modern operating systems will load hard-coded strings into a memory page marked read-only, so the program gets a fatal-by-default signal if it tries to write there).
Why would free
do stuff it wasn't supposed to do when given a bad address? Because one way that memory allocators have been traditionally written is to allocate slightly larger chunks then you asked for and store metadata for that allocation at the front of that space, and/or to write metadata needed for reusing that memory into the space once you've freed it. In allocators like that, every free
leads to some memory being overwritten near the address you gave it. This kind of design has led to many bugs and exploitable security vulnerabilities in code, but last I checked it persists in some C implementations.
Now onto your bigger-picture goal:
You were seemingly expecting =
to copy the characters from one location to the other. This can make sense when coming from higher-level languages, but C doesn't have such syntactic sugar. Instead, in C, =
on a memory address ("pointer") copies the memory address.
It's also probably not obvious, but in C, a string literal expression mostly works like a pointer - the type of the expression "Earth"
is actually char *
.
Anyway, as others have pointer out, you would use a function like strcpy
to copy the characters from "Earth" into the newly-allocated storage. You could also copy the characters yourself with a loop, but this isn't recommended in most cases because the standard library implementation: says what you mean in a way that C devs can immediately understand; might be optimized to perform better than a naive byte-by-byte loop, and; might be understood by your compiler's optimizer passes.
答案2
得分: 0
由于程序中的常量字符串存储在数据段的只读区域,你不能随意释放它!使用strcpy将字符串复制到你分配的内存中。
理解应用程序二进制段非常重要。
在C语言中,有这些段:
栈
堆
BSS(未初始化数据段)
数据(包括已初始化的只读区域和已初始化的读写区域)
代码(包含可执行指令)
英文:
Since constant string store in program data segment read-only arena and you can't just free it!!
use strcpy to copy str to your allocated memory instead
Understanding application binary segement is really important
in c, have these segments :
Stack
Heap
BSS (Uninitialized Data Segment)
Data ( has initialized read-only and initialized read-write area)
Code (contains executable instructions)
答案3
得分: 0
最可能的情况是,程序正在尝试释放已经被释放或者没有使用malloc函数进行动态分配的内存。要解决这个问题,可以使用类似strcpy()的方法将字符串字面值的内容复制到malloc()分配的内存中。
英文:
Most likely, the program is attempting to release memory that has already been released or memory that was not dynamically allocated using the malloc function . To resolve this problem, use a method like strcpy() to copy the contents of the string literals into the memory allotted by malloc() .
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论