0

私はOS Xで作業しています。次のような簡単なコードを書きました

pTest       =   (char*)malloc(sizeof(char) * 3);

pTest[0]    =   0;
pTest[1]    =   1;
pTest[2]    =   2;

pTest       =   (char*)realloc(pTest, sizeof(char) * 2);

printf("%d %d %d %d\n", pTest[0], pTest[1], pTest[2], pTest[3]);
pTest[3]    =   100; // memory access violation.

このコードでアクセス違反が発生しない場合、なぜ realloc が必要なのですか? 小さなサイズのヒープ セグメントにメモリが割り当てられていますが、必要なのはpTest[100]pTest[2048]、などのさらなるインデックスにアクセスすることだけですpTest[65536]
誰かがアクセス違反を引き起こさない理由を説明できますか?

4

5 に答える 5

4

void *realloc(void *ptr, size_t size);

このrealloc()関数は、ptr が指すメモリ ブロックのサイズを size バイトに変更します。コンテンツは、領域の開始から古いサイズと新しいサイズの最小値までの範囲で変更されません。

サイズを縮小しています:

pTest   =   (char*)realloc(pTest, sizeof(char) * 2);
                                      ^
                                      | 
                                     changed size of array to two chars only

この最大インデックス値の後、次のようになり1ますpTest[1]

インデックス値が 1 を超えると、メモリ違反が発生します - 不正なメモリ アクセス - 実行時の未定義の動作。

于 2013-08-01T09:05:04.820 に答える
3

あなたがそこでしていることは、未定義の動作です。accvio の「可能性」、segfault の可能性があります。一方、あなたの猫にメールを送るかもしれません。未定義であるため、未定義の動作に依存することはできません。

于 2013-08-01T09:04:56.657 に答える
0

メモリアロケータがどこからメモリを取得し、どのサイズで取得するかによって完全に異なります。

通常、メモリは「通常の」ヒープ領域の最後から取得され、必要に応じて拡張されます。解放後、OS への呼び出しの数を最小限に抑えるために、可能な限りすべてをすぐに解放しないようにするために、特定のヒステリシスがあります。

さらに、メモリがヒープの最後にない場合、解放されたメモリは で使用可能なメモリ領域に追加されますmalloc()。空きメモリを管理するリンク リストの一部になるために内容が変更される場合がありますが、プロセスに割り当てられたメモリの一部であるため、読み取りアクセスは成功します。

ヒープの最後に非常に大きな部分がありfree()、ヒープが実際に縮小する場合、またはメモリ ブロックが大きすぎて を介して割り当てられた場合にのみmmap()、後でアクセスするfree()と実際にアクセス違反が発生します。

于 2013-08-01T09:29:40.723 に答える
0

まず、ヒープmeallocにメモリ ストアを使用します。0,1,2

次にrealloc(pTest sizeof(char )*2)、 ;を使用します。記憶を切り裂いて、今しかない0,1

印刷すると、解放されたメモリpTest[3],からデータが読み取られます。メモリがまだ使用されておらず、古い値のままである可​​能性がありますが、安全ではありません。

次に、 に値を指定しpTest[3]ます。しかし、配列サイズが 2 しかないことに気づきましたか? あなただけが使えるpTese[0] and pTest[1]!

私はあなたのコードを修正しました:

pTest       =   (char*)malloc(sizeof(char) * 3);

pTest[0]    =   0;
pTest[1]    =   1;
pTest[2]    =   2;

pTest       =   (char*)realloc(pTest, sizeof(char) * 4);// at lest 4 

printf("%d %d %d \n", pTest[0], pTest[1], pTest[2]);//  pTest[3]) is still unkonw;
pTest[3]    =   100; //it is ok now
于 2013-08-01T09:08:13.503 に答える
0

割り当てられたメモリ外へのアクセスは未定義です。通常、何らかのセグメント境界に到達するまで、アクセス違反は発生しません。それ以外の場合、前述のように、動作は未定義です。

配列を操作するときは、インデックスの境界内にとどまります。配列インデックス値のアクセス違反の警告が必要な場合は、自分で追加する必要があります。

また、 realloc は、最初に割り当てた最後のバイトが必要ないという手がかりをメモリマネージャーに与えるだけです。メモリ マネージャーは、同じポインター値または他の新しいポインター値を返す場合があります。唯一の懸念事項は、メモリ割り当てを超えないようにすることです。その場合、未定義の動作が発生し、場合によってはアプリケーションのずっと後の段階で発生します。

于 2013-08-01T09:11:09.007 に答える