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 で実行すると、stl_algobase.h の 743/744 行目でスタックしていることがわかります。

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 に問題があり、シェル変数 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 に答える