2011-09-12 21 views
1

I 2次元配列上のmallocを行うため、この方法を使用し、私の情報源は http://c-faq.com/aryptr/dynmuldimary.htmlModify malloc strategy for 2D Array so malloc succeedsです:2D配列のC malloc:なぜセグメンテーションフォルトがないのですか?

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

    array = malloc(5 * sizeof(long *)); 
    for (int i = 0; i < 5; i++) 
     array[i] = malloc(3 * sizeof(long)); 

    array[4][2] = 515; 
    array[4][3] = 212; 
    array[4][10000] = 3; 

    printf("%ld\n", array[4][10000]); 

    return 0; 
} 

私の質問は、私はのいずれかの実行でセグメンテーションフォールトを取得しないのはなぜ です戻りの前に最後の3行?それは安全です(フリーの存在を無視して)?

+1

は、通常、OSに依存して、有効なメモリにアクセスしているかどうかをチェックします。 –

+2

C(C++ではなく)を実行している場合、他の型への 'void *'ポインタの省略をおすすめします。特に、 'array =(long **)malloc(5 * sizeof(long *));'を 'array = malloc(5 * sizeof * array);に変更します。 'は、' malloc'に対して正しいサイズを生成します。 (私は 'array [i] = malloc(3 * sizeof ** array);同様にもう1つ呼び出す) –

+0

私自身の境界を越えてアクセスしようとしない限り、安全です? –

答えて

0

オペレーティングシステムは、アプリケーションにページ単位(通常は4 KB)でメモリを割り当てます。効率を上げるために、巨大なページ(例:2 MB)を使用することが可能です。

最初のページ0は決して割り当てられません。また、アクセスしようとするとセグメンテーション違反が発生します。例えば0〜4095の任意のポインタにアクセスすると、ほとんどのシステムでセグメント化エラーが発生します。

ただし、ページが割り当てられたら、セグメンテーションフォルトなしでそのページの一部を読み書きすることができます。 (コードページは通常書き込みから保護されます)

mallocを使用すると、必要なページがあることが確認されます。しかし、あなたが持っているメモリにアクセスするだけで、好きなように変更することができます。

一般的に、これは有用ではありませんが、無効な方法でメモリにアクセスしてもセグメンテーションフォールトが保証されない理由を説明するのに役立ちます。

注:mallocは小さな構造を持っています。 8バイト、ブロック自体の前に割り当てられた各ブロックの先頭で、これを破損するとmallocfreeは正しく動作しません。

6

未定義の動作が呼び出されています。定義されていない動作は、その名前が示すように、セグメンテーション・フォルトを引き起こすように定義されていません。そのコードは、そのメモリの値をあなたが与えている値に設定したり、割り当てを完全に無視したり、わかっているすべてのものに対してピザを注文することができます。

+3

+1はピザを注文します。ピザが欲しい... –

1

mallocは、メモリがプロセスにどのように割り当てられるかの一部に過ぎません。

メモリはオペレーティングシステムによって全ページで処理されるため、4kBまたは4MB(またはその他のサイズ)のチャンクが大きい。ユーザー空間でのプロセスは、好きなようにページを切り詰める自由を持っています。

mallocは2つの役割を果たし:割り当てられたチャンクにそれらのページ

だから私は何が起こっているのか賭けを分割

  • は、あなたがどこかに着陸しているOSから

    • リクエストページですあなたが所有しているページでは、あなたが割り当てたチャンクではありません。限り、OSの懸念はOKです。

  • 0

    あなたが所有していないメモリに書き込んでも必ずしもセグメンテーションフォールトが発生するとは限りません。

    これは、他のポインタを上書きした後に、後でセグメンテーションフォルトを引き起こしているポインタにアクセスしようとしたときです。そのため、これらのエラーは通常、デバッグするのが困難です。

    0

    これは古典的なヒープ破損のバグです。それはクラッシュするかもしれないし、クラッシュしないかもしれない - あなたがどれほど幸運であるかによる。

    ヒットのうち、使用されていない可能性が高い、または致命的ではない方法で破損している可能性が高い部分を上書きしています。

    関連する問題