2

なぜこれが「テスト」を出力するのですか?:

    char *str;
    str = (char *)malloc(1);
    str[0] = 't';
    str[1] = 'e';
    str[2] = 's';
    str[3] = 't';

私は文字列を動的に展開しようとしており、malloc / reallocがどのように機能するかを理解しようとしています。上記の動作は、char *を展開するためにmalloc()/ realloc()が推奨されることに関して私を混乱させます。

前もって感謝します。

4

3 に答える 3

4

未定義動作とは、何かが起こる可能性があることを意味します。「機能している」ように見えること、まったくないこと、またはセグメンテーション違反を含みます。サンプルコードは確かに悪いですが、C標準は、それが「有用な」ことを行うことや、コンパイル時または実行時に必ずしも「悪い」ことが起こることを保証しません。

于 2013-03-12T19:02:20.660 に答える
2

「公式に」割り当てられたメモリの終わりを超えて書き込んでいます。ほとんどのメモリ割り当てシステムには、内部で使用する最小サイズがあり、実際にはその境界を超えていない可能性があるため、コードは機能しているように見えます。文字列を十分に長くすると、最終的にOSにとって重要な境界を通過し、プログラムがクラッシュします。

に乱数を割り当てて、strそれをポインタとして扱うこともできますが、実際に機能することがよくあります。しかし、何を上書きしているのかわかりません。あなたのメモリオーバーランと同じです。メモリアロケータは、プログラム内の他の何かを上書きするのに十分なほど密に割り当てをパックする場合があります。

常に、配列の境界を超えないようにする必要があります 。EVER。バッファオーバーラン(およびアンダーラン)は、まさに多くのハックがシステムに侵入するために利用するものです。それらを許可しないようにしてください。そうすれば、かなりの数の古いコードがすでに存在していることになります。

于 2013-03-12T19:05:59.330 に答える
1

このコードは明らかに間違っています。明らかに、配列の境界を越えてメモリにアクセスしています。

それが機能する理由は次のとおりです。

  • 無効なメモリアクセスをすべて検出するメカニズムはありません。このような試みの多くはセグメンテーション違反を引き起こしますが、毎回発生するわけではありません。多くの場合、このようなバグのあるコードは、確率変数などを上書きするだけです。これが、このようなデバッグの問題がすぐに悪夢になる理由の1つです。Valgrindに慣れることをお勧めします。

  • この特定のケースではmalloc()、割り当てられたメモリのチャンクを(少なくとも)4の倍数に切り上げるので、この場合は期待どおりに機能する可能性があります。しかし、それでもそれはバグです。

  • また、文字列を明示的に終了しないでください。また、動作は実際にはランダムでありstr[4]、実際には任意の値を持つことができます。ヒープアロケータの実装から純粋な偶然の一致まで、多くのことに依存します。

于 2013-03-12T19:06:32.060 に答える