0

こんにちは、友人がこのコードを見せて、配列/スタック バウンド チェックについて説明しました。

#include <stdio.h>

void foo() {
    unsigned long long a[1];
    a[3] -= 5;
    printf("Print me!\n");    
}

int main(){ 
    foo();
    return 0;    
}

このコードを実行すると、常に「Print me!\n」と表示され続け、停止しません。MingW 64bit でコードをコンパイルしました。ここで何が起こっているのですか?なぜテキストを印刷し続けるのか、誰かに説明してもらいたいです。

4

3 に答える 3

3

a[3] -= 5;配列の範囲外で var を変更したため、コマンドによってスレッド スタックが破損しました。この動作はまったく予測できず、他のシステムでは異なる場合があります。スタックの戻りアドレスを変更してprintfを呼び出すだけだと思います

理解したい場合は、逆アセンブラを使用してください。

于 2012-10-13T17:57:30.157 に答える
1

foo() でスタックフレームの外側の値を変更しています。

具体的には、リターン アドレスから 5 を引いています (これが通常の x86-32 呼び出し規約の場合)。

メインの foo() 呼び出しが次のようなものにコンパイルされている場合

call ebp-126(call short offset) 命令の長さは 5 バイトです。

したがって、リターンはコールの後ではなく、コールに送られます。そして、呼び出しが再度実行されます。

ただし、これは、呼び出し規則とコンパイラによって発行される特定の命令の両方に依存するため、コードが取得するのと同じくらい移植性が低く、未定義です。

于 2012-10-13T17:56:45.970 に答える
0

スタック バッファ オーバーフローの可能性があるようです。

スタック配列で未定義のインデックスを参照していますa。これにより、スタックの戻りアドレスが上書きされる可能性があります。

関数が関数に渡されると、操作によって関数が呼び出される前に戻りアドレスが値に設定される可能性がreturnあるため、関数が再びmain実行される可能性が最も高くなります。foo- 5

于 2012-10-13T17:56:03.590 に答える