Когда вы освобождаете память, что происходит с указателями, указывающими на эту память? Они сразу становятся недействительными? Что произойдет, если позже они снова станут действительными?
Конечно, обычный случай, когда указатель становится недействительным, а затем снова становится «действительным», — это когда какой-то другой объект выделяется в память, которая использовалась ранее, и если вы используете указатель для доступа к памяти, это очевидно. неопределенное поведение. Висячая память указателя перезаписывает урок 1, в значительной степени.
Но что, если память снова станет доступной для того же выделения? Для этого существует только один стандартный способ: realloc()
. Если у вас есть указатель где-то внутри malloc()
блока памяти со смещением > 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;
}