我从一段相对简单的代码中观察到一些奇怪的行为,想问问是否有人以前见过这样的行为。
下面的代码是在函数内分配内存并返回指向它的指针的基本示例(您可以在大多数 C 教科书中找到类似的代码)。
// BROKEN CODE EXAMPLE:
// Function which returns a char pointer
char *f() {
// Allocate some memory; 1024 is merely an example
char *c = malloc(1024);
return c;
}
// Calling function
void main_f() {
char *c = f();
// Do some stuff here
free(c);
}
在我的实际程序中,main_f()
函数从其主循环中重复调用。当 main_f()
函数被编译到程序的可执行文件中或来自可执行文件链接到的库时,一切都会按预期工作。
但是,如果代码驻留在可执行文件使用 dlopen() 加载的共享库中,则会发生奇怪的事情:在随机次数的迭代(可能是 5、15、50 或甚至更多)代码因 SIGSEGV 崩溃。调试代码表明崩溃恰好发生在调用 return
时。
更奇怪的是,通过反复试验发现,解决崩溃的一个简单方法不是从 f()
函数返回指针,而是为该函数提供一个双指针:
// WORKING CODE EXAMPLE:
// Modify the function to use a double pointer
void f(char **c) {
// Allocate some memory; 1024 is merely an example
*c = malloc(1024);
}
// Calling function
void main_f() {
char *c;
f(&c);
// Do some stuff here
free(c);
}
实际代码是 GTK+ 程序的一部分,并在 GLib 主循环内运行。上述程序不会创建额外的线程,而是通过计时器每分钟执行一次上述节(并且运行不会重叠)。共享库仅在初始化时通过 dlopen() 加载一次。
难道 malloc()、dlopen() 和 GLib 并不总是能很好地发挥作用吗?实际的程序仅适用于 UNIX,因此我们认为没有必要求助于 GLib 提供的可移植函数,例如 g_malloc()
或更大的对象,例如 GModule
;不过,更喜欢它们有什么意义吗?
还有其他人看到过这个问题吗?
最佳答案
简短的回答,你要么有错误,要么硬件不好。我强烈怀疑有错误。如果出现错误,则要么是指针失控并破坏了代码,要么是不正确地释放了内存。
我认识到您提供了一个简化的示例来演示发生的情况,但即使在您的示例中也存在错误。您malloc
但从未测试错误。如果您稍后尝试释放 NULL,这可能就是原因。
事实上,您可以对代码进行微小的修改,从而神秘地解决问题,这只会强化错误理论。
但是,如果您 100% 确定没有错误(然后您再次检查并确实确定没有错误),那么您的硬件问题很可能只是坏的内存。尝试在另一台机器上运行您的代码。如果它在那里崩溃了——那就是一个错误。否则,简单的 RAM 交换应该可以确认您是否存在硬件故障。
关于c - 在 dlopen() 库中返回指向 malloc() 的指针时出现 SIGSEGV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28318565/