c - 在 dlopen() 库中返回指向 malloc() 的指针时出现 SIGSEGV

标签 c malloc glib dlopen gtk2

我从一段相对简单的代码中观察到一些奇怪的行为,想问问是否有人以前见过这样的行为。

下面的代码是在函数内分配内存并返回指向它的指针的基本示例(您可以在大多数 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/

相关文章:

c++ - 为什么 CUDA 固定内存这么快?

c - 挂起进程调试

c - 数组a和&a的起始地址

c - glib GHashtable 取消引用 gpointer

c - Bluez D 总线 : Bluetooth speaker Play/Pause/Next/Previous button handling

gtk - 使用 glib.string.escape() 时如何转义特殊字符

c - 此代码如何反转数字中的位?

c - 在 C 中交换指针数组中的 2 个元素(到不同长度的字符串)

c++ - malloc.c:2451 在使用 vector 的 std::vector 的程序中

c - 对 2D 数组使用 malloc 时出现段错误