1

次の情報が必要です。

関数を呼び出すときに、powerpc と intel プロセッサはどのようにスタックを割り当てますか? - powerpc と intel x86 プロセッサなど、それぞれのケースで決定されるスタック サイズの基準は何ですか - スタックに格納されている引数と戻りアドレスの場所。

基本的に、それぞれの場合にレイアウトをスタックする必要があります。

Intel マシンでプログラムがクラッシュ (セグメンテーション違反) し、powerpc で正常に動作している状況があります。クラッシュの原因が見つかりました。コード スニペットは以下のとおりです。

int function_a(int a)
{
   int local_var = 1;
   int ret_var;

   ret_var = function_b(&local_var);

}

int function_b (int* local_var_in_calld_fn)
{

   while (some_condition)
   {
      *local_var_in_calld_fn = some_computed_value; /* Cause of crash */
      local_var_in_calld_fn++; 
   }
   return something;
}

スタック上に「ある可能性がある」アドレスで値が更新されたため、クラッシュします。コードは特定の場所で正確にクラッシュすることはありませんが、gdb でデバッグすると、x86 マシンでこの機能を終了した後、外部のどこかでクラッシュします。

スタックが壊れているのではないかと疑っていますが、powerpc ではクラッシュしていません。

ありがとう

4

2 に答える 2

3

ここには明らかなスタック オーバーランがあります。
function_a単一の へのポインターを取得しint、インクリメントして (スタック内の別の場所を指すように)、書き込みます。

スタック オーバーランの結果は非常に予測不可能です。これは、呼び出し規則だけでなく、変数の順序付けやインライン化など、まったく標準化されていないコンパイラの決定にも依存します。

あるケースではクラッシュし、別のケースではクラッシュしない理由を理解することにこだわるつもりはありません。
直したほうがいい。

于 2012-05-17T06:37:08.033 に答える
0

OSは、プロセッサではなく、スタックの割り当てを担当します。PowerPCプロセッサは、スタックを認識も気にもしません。「スタックポインタ」は慣例によりr1完全に正常なレジスタですが、これはプラットフォームに依存します。あなたはこれがどのプラットフォームで実行されているかを述べていません。

この場合、クラッシュは、local_var_in_calld_fn++;未定義の動作である行によって引き起こされます(おそらくあなたが意味する*local_var_in_calld_fn++;)。問題は、「なぜ未定義動作がクラッシュしないのか」ということです。答えは簡単です:

未定義の動作は未定義であるため、クラッシュしないことを含め、絶対に何でも起こり得ます。

それはさておき、クラッシュしない理由の最も簡単な説明は、some_conditionPPCでfalseと評価されるためです(シングルコアであるため、ロックの競合が少なく、クラッシュにまだ気づいていません)。

これがクラッシュしない場合も考えられます。

  • この特定のプラットフォームでは、スタックが大きくなります(一般的なものがこれを行うかどうかはわかりません)。これは*local_var_in_calld_fn、スタックを効果的に拡張するための書き込みがスタックを破壊する可能性があることを意味しfunction_b()ますが、呼び出し元のスタックは破壊しません。
  • function_b()は「リーフ関数」(つまり、関数呼び出しを行わない)であるため、LRをスタックに保存する必要はありません。これは、への書き込み*local_var_in_calld_fnがリターンアドレスを壊さないことを意味します。
  • some_conditionスタックが不足しないように、すぐにfalseになります。
于 2012-06-11T19:27:41.647 に答える