if(0) の 4 つの nop でバグが修正され、ワー​​ルドが意味をなさなくなりました

ほとんどの場合、コードをさりげなく変更して問題を解決する場合、それは何らかのメモリ破損の問題です。適切な分析を行うために実際のコードを確認する必要があるかもしれませんが、入手可能な情報に基づいて、それが私の最初の推測です.


これは、直接 (ポインターを介して) または間接的に (配列の末尾を通過することにより)、誤ったポインター演算です。すべてのアレイを確認してください。配列が次の場合は忘れないでください

 int a[4];

その場合、a[4] は存在しません。

あなたがしていることは、スタック上の何かを誤って上書きすることです。スタックには、ローカル、パラメーター、および関数からの戻りアドレスの両方が含まれます。余分なヌープが治る方法で、返信アドレスを損傷している可能性があります。

たとえば、戻りアドレスに何かを追加するコードがある場合、余分な 16 バイトの noops を挿入すると問題が解決します。これは、コードの次の行を過ぎて戻るのではなく、いくつかの noops の途中に戻るためです。

戻りアドレスに何かを追加する方法の 1 つは、たとえば、ローカル配列またはパラメーターの末尾を超えることです。

  int a[4];
  a[4]++;

他のことで数日忙しかった後、私はこれに戻ってきて、すぐにそれを理解しました.申し訳ありませんが、コードをすぐに投稿しませんでしたが、問題を示す最小限の例を見つけるのは困難でした.

根本的な問題は、再帰関数で return ステートメントを省略したことです。私が持っていた:

bool function() {
    /* lots of code */
    function()
}

あるべき時期:

bool function() {
    /* lots of code */
    return function()
}

これが機能したのは、最適化の魔法によって、適切な値が適切なタイミングで適切なレジスターにたまたまあり、適切な場所に配置されたからです。

このバグは、最初の呼び出しを独自の特別なケースの関数に分割したときに最初に導入されました。そして、その時点で、この最初のケースが一般的な再帰関数に直接インライン化されていることとの違いは、余分な nops でした。

その後、理由はよくわかりませんが、この最初のケースをインライン化すると、適切な値が適切なタイミングで適切な場所に配置されず、関数がジャンクを返すことになりました。