malloc()がエラーを引き起こさない後に境界外にポインターを書き込む

StackOverflow https://stackoverflow.com/questions/4534780

  •  13-10-2019
  •  | 
  •  

質問

以下のコードを試してみると、正常に機能します。私は何かが足りませんか?

main()
{
    int *p;
    p=malloc(sizeof(int));
    printf("size of p=%d\n",sizeof(p));
    p[500]=999999;
    printf("p[0]=%d",p[500]);
    return 0;
}

malloc(0*sizeof(int))などで試してみましたが、うまく機能します。プログラムは、Mallocをまったく使用しない場合にのみクラッシュします。したがって、配列Pに0メモリを割り当てても、値を適切に保存します。それで、なぜ私はマロックに悩まされているのですか?

役に立ちましたか?

解決

かもしれない 現れる うまく機能するためには、それはまったく安全ではありません。メモリの割り当てられたブロックの外側にデータを記述することで、すべきでないデータを上書きします。これは、セグフォルトやその他のメモリエラーの最大の原因の1つであり、この短いプログラムで機能するように見えることで観察していることが、根本原因を追い詰めることを非常に困難にしています。

読む この記事, 、特に、メモリの腐敗に関する部分は、問題の理解を開始します。

Valgrind あなたが提供するようなメモリエラーを分析するための優れたツールです。

@Davidは良いコメントをしました。実行の結果を比較してください あなたのコード ランニングに 次のコード. 。後者は、IDEONE.com(リンクをクリックしてください)でランタイムエラー(ほとんど有用な出力がありません!)になりますが、前者はあなたが経験したとおりに成功します。

main()
{
    int *p;
    p=malloc(sizeof(int));
    printf("size of p=%d\n",sizeof(p));
    p[500]=999999;
    printf("p[0]=%d",p[500]);
    p[500000]=42;
    printf("p[0]=%d",p[500000]);
    return 0;
}

他のヒント

メモリを割り当てない場合、Pにはゴミが入っているため、書くことは失敗する可能性があります。有効なmallocコールを作成したら、Pは有効なメモリの位置を指しており、それを書くことができます。あなたはあなたが書くべきではない記憶を上書きしていますが、誰もあなたの手を握ってそれについてあなたに話すつもりはありません。プログラムとValgrindなどのメモリデバッガーを実行すると、わかります。 Cへようこそ

メモリの終わりを過ぎて書くことは未定義の行動™です。つまり、プログラムがまるでやったことが完全に合法であるかのように動作することを含めて、何でも起こり得ることを意味します。あなたがやったかのようにあなたのプログラムを実行した理由 malloc(501*sizeof(int)) 完全に実装固有であり、実際に月の位相を含むあらゆるものに固有のものです。

これは、malloc()で使用しているサイズに関係なく、Pにあるアドレスが割り当てられるためです。ただし、サイズがゼロでは、メモリが割り当てられていないため、無効なメモリを参照しますが、動作は未定義になりますが、プログラムクラッシュを引き起こさない場所内にある可能性があります。

Malloc()を使用しない場合、それはゴミ箱の場所を指しており、プログラムのクラッシュを引き起こす可能性が高いアクセスを試みることになります。

malloc(0*sizeof(int))で試しました

サイズが通過した場合、C99によると malloc 0で、cランタイムはnullポインターを返すか、リクエストが非ゼロ割り当てであるかのように割り当てを返すことができます。したがって、実装が定義されている(例:いくつかの実装はゼロ長さのバッファーを返します)、あなたの場合はヌルポインターを取り戻すことはできませんが、使用してはいけないポインターを使用しています。ヌルポインターを取り戻すことができます。

malloc()を呼び出すと、メモリの小さな塊があなたのために大きなページから刻まれています。

    malloc(sizeof(int));

実際には、32ビットマシンに4バイトを割り当てません(アロケーターは最小サイズまでパッドにパッドをパッドします) +寿命を越えてチャンクを追跡するために使用されるヒープメタデータのサイズ(チャンクはサイズに基づいてビンに配置され、使用したマークされていますまたはアロケーターで無料)。 hxxp://en.wikipedia.org/wiki/mallocまたはより具体的にはhxxp://en.wikipedia.org/wiki/malloc#dlmalloc_and_its_derivatives linuxでこれをテストしている場合。

したがって、あなたの塊の境界を超えて書くことは、必ずしもあなたがクラッシュすることを意味するわけではありません。 P+5000では、その最初のチャンクに割り当てられたページの境界の外側に書いていないため、有効なマッピングアドレスに技術的に書き込みます。メモリの腐敗へようこそ。http://www.google.com/search?sourceid=chrome&ie = utf-8&q=heap+overflows

私たちの CheckPointer ツールはこのエラーを検出できます。 Pの割り当てが4バイトの塊にあることを知っているため、割り当てが行われ、Pが割り当てられた領域の外側にあります。 P [500]の割り当てが間違っていることがわかります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top