4

运行linux内核3.6.6-1,gcc 4.7.2-2,程序如下:

1 #include <vector>
2 using namespace std;
3 int main ()
4 {
5     vector<size_t> a (1 << 24);
6     return 0;
7 }

永远不会从第 5 行返回。

当我在 gdb 中运行时,我看到它卡在第 743/744 行的 stl_algobase.h 中:

0x000000000040101c in std::__fill_n_a<unsigned long*, unsigned long, unsigned long> (__first=0x7fffeffd8060, __n=16777216, __value=@0x7fffffffe0a8: 0)
    at /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_algobase.h:743
740     __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value)
741     {
742       const _Tp __tmp = __value;
743       for (__decltype(__n + 0) __niter = __n;
744        __niter > 0; --__niter, ++__first)
745     *__first = __tmp;
746       return __first;
747     }

__niter 只是保持在值 1 并且从不倒数到 0。

此行为仅在我的系统运行一段时间后才会发生。当它发生时,整个系统似乎很无聊。也就是说,gui 很快停止响应,但我可以 ssh 进入并做一些事情,但最终整个系统变得无法使用,我重新启动。

重新启动后,上述程序按预期运行。

显然,问题不在于我的程序。这只是一些更大问题的症状。

我的问题是:接下来我该怎么做?

我检查了所有错误日志,但一无所获。我没有遇到硬件异常或类似的情况,因此很难准确判断我的系统何时进入此状态。

我没有想法,所以任何帮助将不胜感激。

编辑:

我将编译器选项更改为-g -Wall并得到相同的结果。

这是 __fill_n_a 的反汇编(带有新选项):

  1 0x00000000004010bd <+0>:    push   %rbp
  2 0x00000000004010be <+1>:    mov    %rsp,%rbp
  3 0x00000000004010c1 <+4>:    mov    %rdi,-0x18(%rbp)
  4 0x00000000004010c5 <+8>:    mov    %rsi,-0x20(%rbp)
  5 0x00000000004010c9 <+12>:   mov    %rdx,-0x28(%rbp)
  6 0x00000000004010cd <+16>:   mov    -0x28(%rbp),%rax
  7 0x00000000004010d1 <+20>:   mov    (%rax),%rax
  8 0x00000000004010d4 <+23>:   mov    %rax,-0x10(%rbp)
  9 0x00000000004010d8 <+27>:   mov    -0x20(%rbp),%rax
 10 0x00000000004010dc <+31>:   mov    %rax,-0x8(%rbp)
 11 0x00000000004010e0 <+35>:   jmp    0x4010f7 <std::__fill_n_a<unsigned long*, unsigned long, unsigned long>(unsigned long*, unsigned long, unsigned long const&)+58>
 12 0x00000000004010e2 <+37>:   mov -0x18(%rbp),%rax
 13 0x00000000004010e6 <+41>:   mov -0x10(%rbp),%rdx
 14 0x00000000004010ea <+45>:   mov %rdx,(%rax)
 15 0x00000000004010ed <+48>:   subq $0x1,-0x8(%rbp)
 16 0x00000000004010f2 <+53>:   addq $0x8,-0x18(%rbp)
 17 0x00000000004010f7 <+58>:   cmpq $0x0,-0x8(%rbp)
 18 0x00000000004010fc <+63>:   setne  %al
 19 0x00000000004010ff <+66>:   test   %al,%al
 20 0x0000000000401101 <+68>:   jne    0x4010e2 <std::__fill_n_a<unsigned long*, unsigned long, unsigned long>(unsigned long*, unsigned long, unsigned long const&)+37>
 21 0x0000000000401103 <+70>:   mov -0x18(%rbp),%rax
 22 0x0000000000401107 <+74>:   pop %rbp
 23 0x0000000000401108 <+75>:   retq

我还运行了系统的内存诊断工具,没有出现任何错误,并且按照 DL 的建议,运行 memtest86 时没有出现任何错误。

编辑:

通过在不同的机器上运行相同的代码,我已经确认这不是硬件问题。另一台机器安装了相同的内核和编译器软件,它以同样的方式失败。

我对 ImageMagick 持怀疑态度。这似乎只有在我运行了许多 ImageMagick 转换调用的脚本之后才会发生。我之前在使用 ImageMagick 时遇到过问题,不得不设置 shell 变量 MAGICK_THREAD_LIMIT=1。

4

1 回答 1

2

您描述的总体症状听起来像是内存不足。正如评论者所指出的,如果系统内存使用率没有读到高,这可能是由于某种 RAM 问题。

你说:

__niter 只是保持在值 1 并且从不倒数到 0。

但这不太有意义——__niter 应该从 16777216 开始并倒数到 0。如果你随机闯入这个程序,它几乎肯定会在这个循环中,但 __niter 的值几乎肯定不会1,如果你单步执行循环,它似乎只是循环。我高度怀疑 gcc 4.7 发布的调试信息(实际上,自 gcc 4.0 以来,它几乎是一个问题),因为 gdb 似乎经常打印出错误的局部变量值,但是如果您检查代码并查看和内存/寄存器直接你可以看到正确的值。如果这就是这里发生的情况,那么您的问题可能与该程序无关;它是一种系统不稳定(可能是由于硬件问题),表现为挂起的东西,例如这个程序。鉴于该程序的作用,当它触及以前未触及的页面(出现页面错误)并且内核尝试分配页面时,可能会发生挂起。这表明存在内存问题,但您注意到您已经运行了内存诊断程序。还要确保您没有任何超频或超出规格的东西。

于 2012-11-16T19:20:51.797 回答