現在、かなり大規模な C++ アプリケーション (CPU と RAM の使用量、およびコードの長さの点で大規模 - 100,000 行を超える) で、非常に奇妙なバグが発生しています。これは、デュアルコアの Sun Solaris 10 マシンで実行されています。このプログラムは株価フィードを購読し、ユーザーが設定した「ページ」に表示します (ページはユーザーがカスタマイズしたウィンドウ構造です - プログラムはユーザーがそのようなページを設定できるようにします)。このプログラムは、基盤となるライブラリの 1 つがマルチスレッドになるまで問題なく動作していました。これによって影響を受けるプログラムの部分は、それに応じて変更されました。私の問題に。
約 3 回の実行ごとに、プログラムは起動時にセグメンテーション違反を起こします。これは必ずしも難しいルールではありません。3 回続けてクラッシュし、5 回続けて動作することもあります。興味深いのはセグメンテーション違反です (読む: 痛い)。さまざまな形で現れる可能性がありますが、最も一般的なのは、関数 A が関数 B を呼び出し、関数 B に入るとフレーム ポインタが突然 0x000002 に設定されることです。機能 A:
result_type emit(typename type_trait<T_arg1>::take _A_a1) const
{ return emitter_type::emit(impl_, _A_a1); }
これは単純なシグナルの実装です。impl_ と _A_a1 は、クラッシュ時のフレーム内で明確に定義されています。その命令を実際に実行すると、プログラム カウンター 0x000002 になります。
これは、その関数で常に発生するとは限りません。実際、かなりの数の場所で発生しますが、これはエラーの余地があまりない単純なケースの 1 つです。場合によっては、スタックに割り当てられた変数が理由もなく突然ジャンク メモリ (常に 0x000002) に置かれることがあります。また、同じコードが問題なく実行される場合もあります。それで、私の質問は、何がスタックをひどく壊すことができるのかということです. フレームポインタの値を実際に変更できるものは何ですか? 確かにそんな話は聞いたことがありません。私が考えることができる唯一のことは、配列に範囲外の書き込みをすることですが、それが発生した場合に発生するスタックプロテクターを使用して構築しました。ここでも、スタックの範囲内に収まっています。私もしない 各スレッドには独自のスタックがあるため (これはすべて pthread です)、別のスレッドが最初のスレッドのスタック上の変数を上書きする方法を確認してください。Linuxマシンでこれを構築しようとしましたが、セグメンテーション違反は発生しませんが、約3回に1回フリーズします。