我试图在下面的程序中使用realloc重新分配内存,并在realloc初始内存后检查我使用malloc(i =(int*)malloc(5*sizeof(int)))仍然存在与否,使用下面的程序我能够在使用另一个指针(即*m)检查的realoc之后访问数据.这是正确的行为吗?一旦realloc调用,内存应该是免费的吗?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *i,*jn, *m;
i = (int*)malloc(5 * sizeof(int));
int j,k=10;
for(j=0 ;j<5; j++)
{
i[j] = j;
printf("%d \n",i[j]);
}
for(j=0 ;j<5; j++)
{
printf("%p\n",i++);
}
jn = (int *)calloc(5, sizeof(*i));
for(j=0 ;j<5; j++)
{
printf("%p\n",jn++);
}
i = i-5;
m = i;
printf("m = %p %d\n",(m+1), *(m+1));
i =(int *)realloc(i,8*sizeof(int));
for(j=0 ;j<8; j++)
{
printf("%d\n",i[j]);
}
for(j=0 ;j<8; j++)
{
printf("%p\n",i++);
}
printf("m = %p %d\n",(m+1), *(m+1));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
realloc相当于:
void *
realloc(void *old, size_t newsz)
{
size_t old_sz = internal_function_that_finds_old_size(old);
void *new = malloc(newsz);
if (new == NULL)
return NULL;
memcpy(new, old, oldsz);
free(old);
return new;
}
Run Code Online (Sandbox Code Playgroud)
realloc可以做一些更有效的事情,包括不改变指针而只是使分配的大小更大,它可以使用内核设施将内存映射到其他地方以避免复制等。但一般来说realloc应该被视为完全按照我上面写的那样做,因为这是最坏情况的行为。
现在,说到你的程序。你通过无效的指针接触内存,任何事情都有可能发生。m调用后不再是有效指针realloc。这并不意味着任何人都会阻止您使用它,它只是意味着如果您确实使用它,您的程序将不再保证做任何明智的事情。
首先,realloc可能会决定
分配新的内存块,复制数据并释放原始内存块,或
只需"原位"扩展/收缩原始块,而无需分配新块.
它将选择哪种方法取决于实施和各种其他外部因素.它可能遵循第一种方法.或者它可能遵循第二种方法.您可以通过比较指针i和m之后的值来轻松找出它遵循的方法realloc.
其次,如果realloc决定遵循第一种方法(即分配一个新的内存块),那么旧的块确实被释放了realloc.在这种情况下,尝试访问原始内存位置会导致未定义的行为.
如果realloc决定采用第二种方法(即扩大或缩小"到位"原来的内存块),然后m和i将继续指向同一个位置.在这种情况下,看到相同的数据并不奇怪m.
PS这意味着代码的行为要么是微不足道的,要么是未定义的.它不能真正用于分析行为是否"正确".如果内存确实被释放,你期望发生什么?