我有这个非常简单的源代码作为测试程序:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
fp = fopen("file.txt", "w");
fclose(fp);
fclose(fp);
printf("Completed successfully\n\n");
return(0);
}
我在两台 Ubuntu 服务器上运行此代码,两台服务器都运行 Ubuntu 18.04 LTS。它在 MachA 上 fopen 时死机,而在 MachB 上运行良好并显示“已成功完成”。
确切的错误是:
./testpgm
free(): double free detected in tcache 2
Abort(coredump)
使用 gdb,代码似乎使用了相同的搜索路径。两个系统中都报告了相同的共享库:
(gdb) info sharedlibrary
From To Syms Read Shared Object Library
0x00007ffff7dd3f10 0x00007ffff7df4570 Yes /lib64/ld-linux-x86-64.so.2
0x00007ffff7a032d0 0x00007ffff7b7bb7c Yes /lib/x86_64-linux-gnu/libc.so.6
我能想到的唯一可能影响这一点的是,在问题机器上,我有 g++-9,但我不确定是如何安装它的,因为它似乎不再在 apt-get 中列为可安装包。
问题服务器:
g++-7/bionic-updates,bionic-security,now 7.5.0-3ubuntu1~18.04 amd64 [installed]
g++-8/bionic-updates,bionic-security,now 8.4.0-1ubuntu1~18.04 amd64 [installed]
g++-9/bionic,now 9.3.0-11ubuntu0~18.04.1 amd64 [installed]
工作服务器:
g++-8/bionic-updates,bionic-security,now 8.4.0-1ubuntu1~18.04 amd64 [installed]
是否有可能 apt 中提供了 g++-9 供下载,但后来由于出现问题而被删除?我正在考虑尝试删除该软件包,看看是否能解决问题,但想知道是否有其他人遇到过这个问题,或者对其他需要查找的内容有什么建议。
更新:
根据 waltinator 的建议,我尝试了 strace 命令,但它并没有提供太多关于为什么会发生这种情况的见解。strace 在工作系统和问题系统之间显示的数据几乎相同。唯一的区别是一开始尝试访问正在工作的副本上的 ld.so.preload。
当它真正失败时,我仍然不明白为什么。
工作系统
openat(AT_FDCWD, "file.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
close(3) = 0
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
write(1, "Completed successfully\n", 23Completed successfully
) = 23
write(1, "\n", 1
) = 1
失败的系统
brk(NULL) = 0x5559121ec000
brk(0x55591220d000) = 0x55591220d000
openat(AT_FDCWD, "file.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
close(3) = 0
writev(2, [{iov_base="free(): double free detected in "..., iov_len=40}, {iov_base="\n", iov_len=1}], 2free(): double free detected in tcache 2
) = 41
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7faddf948000
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
ulimit 值的不同仅仅是因为在故障系统上内存量为 64GB,而在工作系统上内存量为 128GB。我想也许是内存不足,但我可以运行其他程序,例如启动 Postgres 并访问数据库。