0

重複の可能性:
配列の終わりを超えて書き込むと、セグメンテーション違反が発生しないのはなぜですか?

何か奇妙なことが起こっていることに気付いたとき、私はちょうどポインターで遊んでいました。たとえば、strcpyを使用して文字列srcを別の文字列dstにコピーする場合は常に、 srcに必要なスペースを割り当てる必要があることを認識しています。

    char *dst,*src = "asdlskafksdhfklshfkshdkfhksdhfçsahdflçsdhfçklshadfç";

    dst = (char*)malloc(1); //only one char allocated
    strcpy(dst,src);

    printf("dst=%s.\n",dst);

このコードは実行しないでください。しかし、それは起こっていません。コードが実行され、srcdstに正常にコピーされ、 dstがチャームのように出力されます。誰か、なぜこれが起こっているのか説明してもらえますか?

4

4 に答える 4

2

C のパフォーマンスの一部は、組み込みのエラー チェック機能があまりないことです。正しい型のポインターが渡されたことはすべてstrcpyわかっていますが、それが指している割り当てられたメモリの量はわかりません。結果のマシン コードは、src ポインターから最初の null バイトまでを読み取り、それを dst ポインターに貼り付けるだけです。他の誰かのメモリを上書きしない場合、エラーはありません。

「他人の記憶」とは?通常、プロセスにはページ単位でメモリが割り当てられます。1 バイトを malloc すると、プロセスにはメモリのページ全体 (おそらく数キロバイト) が与えられ、必要に応じて細かく分割されます。セグメンテーション違反は、プロセスが割り当てられたページの外に書き込もうとした場合や、その他の理由で発生します。エラーは通常、メモリ管理を行っているオペレーティング システムやハードウェアによって生成されます。src は数十バイトしかないため、プロセスのページの外に出る可能性はほとんどありません。src をより長い文字列にすると、期待どおりの segfault が発生する可能性があります。

デバッグに使用されるさまざまな malloc ラッパー ライブラリがあり、さまざまなトリックを使用して C でメモリ エラーをチェックします。 ValgrindElectric Fenceが最も有名です。

PS私はこのものがどのように機能するかについて少しぼやけていますが、「未定義の動作」よりも満足しています。私の説明が欠けているところは自由に編集してください。

于 2012-10-11T22:21:19.840 に答える
2

文字列はヒープに割り当てられます。ヒープのサイズは 1 バイトだけではなく、約 4kb の物理 RAM (デフォルトの Windows コンソール アプリケーション サイズ) です。

ヒープ外のメモリ領域に書き込もうとすると、セグメンテーション違反のみが発生します。ただし、アプリケーションの他の部分のメモリを破壊する可能性があります。ただし、プログラムは非常に小さく、割り当てられたメモリを超えて書き込みを行った直後に終了するため、エラーが発生する可能性はほとんどありません。

于 2012-10-11T22:25:51.303 に答える
1

割り当てられたメモリの外に書き込む場合、結果は未定義です。運が良ければ、セグメンテーション違反が発生します。運が悪いと、他の変数が上書きされます。結論:なんでもあり!

于 2012-10-11T22:17:46.403 に答える
1

リリース ビルドでは、*dst はプロセスのアドレス空間の一部のメモリを指しています。これに書き込むと、アプリのような便利なものがメモリを占有すると、クラッシュします。

デバッグ ビルドでは、コンパイラが *dst を 0 または 0xDEADBEEF などの認識可能な値に設定する可能性が高いため、これを見つけることができます。

于 2012-10-11T22:16:07.937 に答える