应用程序无缘无故地被杀死。怀疑高BSS。怎么调试呢?

时间:2016-10-24 07:12:38

标签: c linux debugging memory

我一直在CentOs6.6中成功运行我的应用程序。最近,硬件(主板和RAM)已经更新,我的应用程序现在已经完全没有任何理由被杀死了。

[root@localhost PktBlaster]# ./PktBlaster
Killed

文件和ldd输出

[root@localhost PktBlaster]# file PktBlaster
PktBlaster: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

[root@localhost PktBlaster]# ldd PktBlaster
not a dynamic executable

strace的输出

[root@localhost PktBlaster]# strace ./PktBlaster
execve("./PktBlaster", ["./PktBlaster"], [/* 30 vars */] <unfinished ...>
+++ killed by SIGKILL +++
Killed

GDB

[root@localhost PktBlaster]# gdb PktBlaster
(gdb) break main
Breakpoint 1 at 0x43d664: file VTP.c, line 544.
(gdb) run
Starting program: /root/Veryx/PktBlaster/PktBlaster 
During startup program terminated with signal SIGKILL, Killed.

调试时,发现bss内存很大(~6GB)。该系统有4GB内存,我认为这可能是问题的原因。

[root@localhost PktBlaster_1Gig]# size build/unix/bin/PktBlaster 
   text    data     bss     dec     hex filename
 375551   55936 6747541120  6747972607  19235e3ff   build/unix/bin/PktBlaster

该应用程序包含许多.h个文件和许多数据结构,因此我很难确定为什么BSS被提升到6GB。

有人可以建议如何识别导致此问题的文件?或者其他更简单的调试方法?

1 个答案:

答案 0 :(得分:2)

似乎问题确实是巨大的BSS大小。 我已要求您在评论中显示LD_DEBUG=all /lib64/ld-linux-x86-64.so.2 /path/to/exe的输出。

/lib64/ld-linux-x86-64.so.2是运行时链接程序,操作系统使用它在execve系统调用期间将二进制文件加载到进程内存中。运行时链接程序负责解析可执行格式,加载内存中的所有部分和依赖项,执行所有必需的重定位等。 将环境变量LD_DEBUG设置为我们指示运行时链接程序生成调试输出的所有内容。

  

[root @ localhost PktBlaster]#LD_DEBUG = all /lib64/ld-linux-x86-64.so.2   /根/ Veryx / PktBlaster / PktBlaster   851:file = / root / Veryx / PktBlaster / PktBlaster [0];生成链接图   / root / Veryx / PktBlaster / PktBlaster:加载共享时出错   库:/ root / Veryx / PktBlaster / PktBlaster:无法映射零填充   pages:无法分配内存

在运行时链接器的源代码(glibc-2.17 elf / dl-load.c,lines~1400)中搜索此错误消息,我们看到:

1393         if (zeroend > zeropage)
1394           {
1395         /* Map the remaining zero pages in from the zero fill FD.  */
1396         caddr_t mapat;
1397         mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
1398                 c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
1399                 -1, 0);
1400         if (__builtin_expect (mapat == MAP_FAILED, 0))
1401           {
1402             errstring = N_("cannot map zero-fill pages");
1403             goto call_lose_errno;
1404           }

dl-loader正在加载BSS段,通过优化将二进制格式存储为只是字节数,必须初始化为零。 Loader尝试通过mmap零初始化内存块(MAP_ANONYMOUS)进行分配,并从操作系统中获取错误:

 15 #define ENOMEM      12  /* Out of memory */

来自man 2 mmap:

  

ENOMEM没有可用内存,或进程的最大数量   映射会被超过。

因此,无论出于何种原因,操作系统似乎都无法满足内存的加载程序请求。使用了一些限制(systemd,进程限制,一些安全LKM,无论如何)或者内核中没有足够的可用内存。

要确定哪个目标文件生成BSS的大部分内容 - 请使用

objdump -j '.bss' -t *.o