2017-01-24 3 views
1

最近私はmallocのCの動作について興味を持ち、面白い動作を見ました。 mallocがNULLであることが判明した後の最初の 'out of bounds'値のように見えます(または、少なくとも、ifによってfalseとみなされるものを返します)。ここ は例示である:mallocの動作は最初に 'out of bounds'の値が常にNULL/0ですか?

int main(){ 

    int i; 
    double * d_ptr = malloc (10 * sizeof (double)); //malloc 10 double 
    for (i=0 ; i<10 ; i++){       // initialise them ... 
     d_ptr[i] = 42; 
    } 

    for (i=0 ;i <50 ; i++){ /// loop obviously trying to go out of bounds 
     if (d_ptr[i]){ 
      printf("i=%d,d[%d]=%f\n",i,i,d_ptr[i]); 
     } 
     else { 
      printf("out of bounds : i=%d\n",i); 
      break; 
     } 
    } 

    printf("exited 'out of bounds loop' safely\n"); 
    free(d_ptr); 
    return 0; 
} 

は、ここで出力です:

i=0,d[0]=42.000000 
i=1,d[1]=42.000000 
i=2,d[2]=42.000000 
i=3,d[3]=42.000000 
i=4,d[4]=42.000000 
i=5,d[5]=42.000000 
i=6,d[6]=42.000000 
i=7,d[7]=42.000000 
i=8,d[8]=42.000000 
i=9,d[9]=42.000000 
out of bounds : i=10 
exited 'out of bounds loop' safely 

は、私の質問は以下のとおりです。

  • 予測可能で、この動作ですか?私は変数の種類の束、mallocのための異なったサイズを試しました、そして、私はいつもループを安全に終了しています。それは予測可能である場合

  • は、は、それが彼らの「サイズ」を知ることが難しいこと、または書き換えの多くを必要とする状況で、ポインタ上のループへの信頼性の高い方法になることができますか?

  • 最後に、それについてもっと深い説明はありますか? mallocを実行する メモリスペースの後に1ワード余分に割り当てると、 が割り当てられますか?
+3

境界外にアクセスすることは、未定義の動作です。何かが起こる可能性があります。それは最も確実に予測できません。 – Barmar

+0

割り当てた後にメモリを解放してから、少し小さいブロックを割り当てて、新しいブロックの終わりにまだ '0'があるかどうかを確認してください。 – Barmar

答えて

2

未定義のビヘイビアを呼び出すと、何かが起こる可能性があります。プログラムがクラッシュしたり、奇妙な結果が表示されたり、正常に動作しているように見えることがあります。この場合、あなたは後者を持っています。

==22701== Memcheck, a memory error detector 
==22701== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al. 
==22701== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info 
==22701== Command: /tmp/x1 
==22701== 
i=0,d[0]=42.000000 
i=1,d[1]=42.000000 
i=2,d[2]=42.000000 
i=3,d[3]=42.000000 
i=4,d[4]=42.000000 
i=5,d[5]=42.000000 
i=6,d[6]=42.000000 
i=7,d[7]=42.000000 
i=8,d[8]=42.000000 
i=9,d[9]=42.000000 
==22701== Invalid read of size 8 
==22701== at 0x4005C4: main (x1.c:13) 
==22701== Address 0x4c18090 is 0 bytes after a block of size 80 alloc'd 
==22701== at 0x4A0610C: malloc (vg_replace_malloc.c:195) 
==22701== by 0x400579: main (x1.c:7) 
==22701== 
out of bounds : i=10 
exited 'out of bounds loop' safely 
==22701== 
==22701== HEAP SUMMARY: 
==22701==  in use at exit: 0 bytes in 0 blocks 
==22701== total heap usage: 1 allocs, 1 frees, 80 bytes allocated 
==22701== 
==22701== All heap blocks were freed -- no leaks are possible 
==22701== 
==22701== For counts of detected and suppressed errors, rerun with: -v 
==22701== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4) 

あなたが見ることができるように、これは適切にmallocさバッファの末尾を越えて読んとして認識されました:valgrindの下にこのプログラムを実行する

次の結果を得ました。

プログラムがクラッシュする可能性があるためではありません。

したがってなしこの動作は予測できません。

2

"この動作は予測可能ですか?"いいえ、それはundefinedです。 「最後に、それについてもっと深い説明がありますか?mallocは割り振られるメモリ空間の後ろに1ワード追加しますか?いいえ、少なくとも私が知っている実装では、決して故意に配列をアクセスしようとしないでください。いくつかのケースではUBで運が良ければ、プログラムは呼び出された後でも期待通りに動作します。time travelling nasal dragonsを気にしてください。

+0

アドバイスと時間の鼻の龍をお越しいただき、ありがとうございました!冷たい事実を覚えておくと良いイメージよりも優れたものはありません。 –

関連する問題