0

我在 glibc 中看到一些奇怪的行为。该代码有一个错误,它会将随机指针传递给fclose()。我本来希望它此时会崩溃,但它会挂在pthread_once()中,并带有以下回溯。该程序不使用任何线程。

#0  0x000000318180ca38 in pthread_once () from /lib64/libpthread.so.0
#1  0x0000003181109d1c in backtrace () from /lib64/libc.so.6
#2  0x0000003181075d34 in __libc_message () from /lib64/libc.so.6
#3  0x000000318107c6fc in malloc_consolidate () from /lib64/libc.so.6
#4  0x000000318107d719 in _int_malloc () from /lib64/libc.so.6
#5  0x0000003181080a4a in calloc () from /lib64/libc.so.6
#6  0x0000003180c0b0df in _dl_new_object () from /lib64/ld-linux-x86-64.so.2
#7  0x0000003180c061ac in _dl_map_object_from_fd () from /lib64/ld-linux-x86-64.so.2
#8  0x0000003180c08563 in _dl_map_object () from /lib64/ld-linux-x86-64.so.2
#9  0x0000003180c13861 in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
#10 0x0000003180c0f304 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#11 0x0000003180c131eb in _dl_open () from /lib64/ld-linux-x86-64.so.2
#12 0x00000031811305d2 in do_dlopen () from /lib64/libc.so.6
#13 0x0000003180c0f304 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#14 0x0000003181130692 in __libc_dlopen_mode () from /lib64/libc.so.6
#15 0x0000003181109c05 in init () from /lib64/libc.so.6
#16 0x000000318180ca40 in pthread_once () from /lib64/libpthread.so.0
#17 0x0000003181109d1c in backtrace () from /lib64/libc.so.6
#18 0x0000003181075d34 in __libc_message () from /lib64/libc.so.6
#19 0x000000318107d0b8 in _int_free () from /lib64/libc.so.6
#20 0x000000318106ba6d in fclose@@GLIBC_2.2.5 () from /lib64/libc.so.6

这是在带有glibc-2.17-20.fc19.x86_64的 Fedora 19 上,并且程序是从 systemd 启动的,因此__libc_message()StandardError=null没有地方输出错误消息。

我已经修复了代码,但这是挂起 glibc 错误还是什么?

4

2 回答 2

3

当然,这不是 glibc 错误:您违反了规则,并且可以得到任何发生的行为。手册页说:

在任何一种情况下,对流的任何进一步访问(包括对 的另一个调用fclose())都会导致未定义的行为。

对触发未定义行为时会发生什么有某种形式的期望在形式上是错误的。行为是未定义的,这意味着没有人可以说出什么是“正确的”和什么是“错误的”。

至于发生这种情况的确切原因,这基本上只对 glibc 实现者感兴趣。也就是说,这个答案暗示了一个解释:fclose()是线程安全的,所以它期望FILE包含一个互斥锁。您正在传递一个解除分配的结构,导致库使用随机垃圾数据作为互斥锁,该互斥锁被锁定。很合理。

于 2014-07-04T09:43:37.150 回答
1

这些天我正在检查类似的回溯,我相信这是一个 glibc 错误,自 Ubuntu 8.04 以来已经存在至少 7 年。

基本上这发生在发生内存损坏之后,不幸的是,__libc_message 自己分配内存。由于堆已损坏,它会尝试再次进行回溯。最后它会导致 pthread_once() 中的死锁。

=EDITED= 我为这个问题找到了一个跟踪器,但它似乎只在 master 分支中修复。 https://sourceware.org/bugzilla/show_bug.cgi?id=16159

于 2015-07-20T02:35:55.007 回答