メモリを解放すると、そのメモリを指すポインターはどうなりますか? それらはすぐに無効になりますか?後で再び有効になった場合はどうなりますか?
確かに、ポインターが無効になり、再び「有効」になる通常のケースは、以前に使用されたメモリに別のオブジェクトが割り当てられることです。ポインタを使用してメモリにアクセスすると、それは明らかに未定義の動作です。ダングリング ポインター メモリの上書きレッスン 1 です。
しかし、同じ割り当てに対してメモリが再び有効になったらどうなるでしょうか。それを実現するための標準的な方法は 1 つだけですrealloc()
。malloc()
'd メモリ ブロック内のどこかに offset へのポインタがある場合> 1
、 を使用realloc()
してブロックをオフセット未満に縮小すると、ポインタは明らかに無効になります。その後realloc()
、ダングリング ポインターが指すオブジェクト型を少なくともカバーするようにブロックを再度拡張し、どちらの場合もrealloc()
メモリ ブロックを移動しなかった場合、ダングリング ポインターは再び有効になりますか?
これは非常にまれなケースであるため、C または C++ 標準を解釈して理解する方法がよくわかりません。以下はそれを示すプログラムです。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
static const char s_message[] = "hello there";
static const char s_kitty[] = "kitty";
char *string = malloc(sizeof(s_message));
if (!string)
{
fprintf(stderr, "malloc failed\n");
return 1;
}
memcpy(string, s_message, sizeof(s_message));
printf("%p %s\n", string, string);
char *overwrite = string + 6;
*overwrite = '\0';
printf("%p %s\n", string, string);
string[4] = '\0';
char *new_string = realloc(string, 5);
if (new_string != string)
{
fprintf(stderr, "realloc #1 failed or moved the string\n");
free(new_string ? new_string : string);
return 1;
}
string = new_string;
printf("%p %s\n", string, string);
new_string = realloc(string, 6 + sizeof(s_kitty));
if (new_string != string)
{
fprintf(stderr, "realloc #2 failed or moved the string\n");
free(new_string ? new_string : string);
return 1;
}
// Is this defined behavior, even though at one point,
// "overwrite" was a dangling pointer?
memcpy(overwrite, s_kitty, sizeof(s_kitty));
string[4] = s_message[4];
printf("%p %s\n", string, string);
free(string);
return 0;
}