如果单独运行,在gdb下Linux上的C代码运行方式会有所不同?

gol*_*ean 3 c linux embedded gdb

我使用code-sorcery工具链在Linux(Fedora)上构建了一个简单的C代码.这适用于ARM Cortex-A8目标.此代码在运行嵌入式Linux的Cortex A8板上运行.

当我为某些测试用例运行此代码时,它malloc为一些大型(10MB)执行动态内存分配(),它会在一段时间后崩溃,如下所示给出错误消息:

select 1 (init), adj 0, size 61, to kill
select 1030 (syslogd), adj 0, size 64, to kill
select 1032 (klogd), adj 0, size 74, to kill
select 1227 (bash), adj 0, size 378, to kill
select 1254 (ppp), adj 0, size 1069, to kill
select 1255 (TheoraDec_Corte), adj 0, size 1159, to kill
send sigkill to 1255 (TheoraDec_Corte), adj 0, size 1159
Program terminated with signal SIGKILL, Killed.
Run Code Online (Sandbox Code Playgroud)

然后,当我使用为目标构建的gdb为相同的测试用例调试此代码时,发生此动态内存分配的点,代码无法分配该内存并malloc返回NULL.但是在正常的独立运行期间,我认为malloc应该没有分配,但奇怪的是可能没有返回NULL,但它崩溃了,操作系统杀死了我的进程.

  1. 为什么在gdb和没有调试器的情况下运行时这种行为会有所不同?
  2. 为什么会malloc失败却没有回归NULL.这可能是可能的,或者我得到的错误消息的原因是别的吗?
  3. 我该如何解决?

谢谢,

-广告

asv*_*kau 6

因此,对于这部分问题,有一个肯定的答案:

为什么malloc失败但没有返回NULL.这可能是可能的,或者我得到的错误消息的原因是别的吗?

在Linux中,默认情况下,用于分配内存的内核接口几乎不会彻底失败.相反,他们设置页面表的方式是,在第一次访问您要求的内存时,CPU将生成页面错误,此时内核处理此问题并查找将用于该内存的物理内存. (虚拟)页面.因此,在内存不足的情况下,您可以向内核询问内存,它会"成功",并且当您第一次尝试触摸它返回的内存时,就是分配实际上失败的时候,会导致您的进程被终止.(或者也许是其他一些不幸的受害者.有一些启发式方法,我对此并不十分熟悉.请参阅" oom-killer ".)

你的一些其他问题,答案对我来说不太清楚.

为什么在gdb和没有调试器的情况下运行时这种行为会有所不同?
可能(只是猜测)GDB有自己的malloc,并且正在以某种方式跟踪您的分配.在某种程度上相关的观点,我实际上经常发现我的代码中的堆错误通常不能在调试器下重现.这令我感到沮丧,让我挠头,但这基本上是我认为必须忍受的东西......

我该如何解决?

这是一个有点大锤溶液(即,它改变了行为的所有过程,而不仅仅是你自己的,它通常不是一个好主意,让你的程序改变这样的全局状态),但你可以写入字符串2/proc/sys/vm/overcommit_memory.查看我从Google搜索中获得的此链接.

失败了...我只是确保你没有超出你期望的分配.

  • 对于像这样的嵌入式系统,运行一组严格控制的进程,关闭overcommit可能是正确的运行方式.如果你有一个合理的标准启动序列,你可以在`/ etc/sysctl.conf`中永久更改. (2认同)