我从一段相对简单的代码中观察到一些奇怪的行为,并想问一下之前是否有人见过这样的代码。
下面的代码是在函数内部分配内存并返回指针的基本示例(在大多数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
;虽然喜欢它们会有什么意义吗?
还有其他人看过这个问题吗?
答案 0 :(得分:1)
简短的回答,你要么有错误,要么有坏的硬件。我强烈怀疑一个错误。如果是一个错误,你有一个指针,它会运行并破坏你的代码,或者你不正确地释放内存。
我认识到您提供了一个简化示例来演示正在发生的事情,但即使在您的示例中也存在一个错误。您malloc
但从未测试过错误。如果您稍后尝试释放NULL,则可能是原因。
您可以对代码进行微小修改,以神秘地解决问题只会加强bug理论。
但是,如果您100%确定没有错误(然后再次检查并且确实没有错误),那么您的硬件问题可能就是糟糕的内存。尝试在另一台计算机上运行代码。如果它在那里崩溃 - 那么这是一个错误。否则,简单的RAM交换应确认您是否有h / w故障。