1

ストレート C と GCC の場合、ポイント先の文字列がここで壊れないのはなぜですか?

#include <stdio.h>

int main(int argc, char *argv[])
{
    char* str_ptr = NULL; 

    {
        //local to this scope-block
        char str[4]={0};
        sprintf(str, "AGH"); 

        str_ptr = str;
    }

    printf("str_ptr: %s\n", str_ptr);

    getchar();
    return 0;
}

|----出力-----|

str_ptr: AGH

|--------------------|

これは、オンライン コンパイラを使用してコンパイルおよび実行された上記のコードへのリンクです。

str文字列リテラルの場合は bss に (基本的には static として) 格納されることを理解していstrますが、スタックに割り当てられたバッファーに sprintf(ing) すると、文字列バッファーは純粋にスタックベースになると思いました (したがって、アドレスはスコープブロックを離れた後は意味がありません)?指定されたアドレスのメモリを上書きするには、追加のスタック割り当てが必要になる場合があることは理解していますが、スタック オーバーフローが発生するまで再帰関数を使用しても、 が指す文字列を破損することはできませんでしたstr_ptr

参考までに、VS2008 C プロジェクトでテストを行っていますが、GCC は同じ動作を示しているようです。

4

2 に答える 2

1

ほとんどの場合、コンパイラは何らかの単純な最適化を行い、その結果、文字列はスタック上の同じ場所に残ります。言い換えれば、コンパイラは、スタックが「str」を格納するために拡張できるようにします。ただし、main のスコープ内でスタックを縮小することはありません。そうする必要がないからです。

変数のアドレスをスタックに保存した結果を本当に見たい場合は、関数を呼び出します。

#include <stdio.h>

char * str_ptr = NULL;
void onstack(void)
{
    char str[4] = {0};
    sprintf(str,"AGH");
    str_ptr = str;
}

int main(int argc, char *argv[])
{  

    onstack();
    int x = 0x61626364;
    printf("str_ptr: %s\n", str_ptr);
    printf("x:%i\n",x);
    getchar();
    return 0;
}

gcc -O0 -std=c99 strcorrupt.c最初のprintfでランダムな出力を取得します。マシンごと、アーキテクチャごとに異なります。

于 2013-08-01T02:47:18.017 に答える