2017-09-28 53 views
2

我想在下面的程序中使用realloc重新分配内存,并在使用malloc(i =(int *)malloc(5 * sizeof(int))malloc)仍然存在或不存在的realloc初始内存之后检查,使用下面的程序我能够访问realoc后,我通过使用另一个指针(即* m)检查的数据。这是正确的行为?或一旦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; 
} 
+1

我会考虑这是一个所有权问题,而不是一个具体的行动。如果'realloc'成功,它将获得传入内存的所有权(操纵它或者释放它)并返回一个可以被调用函数使用(“拥有”)的指针。如果'realloc'失败(返回'NULL'),你的函数保留原始内存的所有权,并且在它完成时应该释放它。 – Myst

回答

4

首先,realloc可能决定

  1. 分配一个新的内存块,复制数据,并释放原来的一个,或

  2. 简单的扩张/收缩原块”地方“而不分配新的。

它会选择哪种方法取决于实施和各种其他外部因素。它可能会遵循第一种方法。或者它可能会遵循第二种方法。通过比较realloc之后的指针im的值,您可以轻松找出它遵循的方法。其次,如果realloc决定遵循第一种方法(即分配新的存储器块),则旧块确实被释放realloc。在这种情况下,尝试访问原始内存位置会导致未定义的行为。

如果realloc决定遵循第二种方法(即扩大或缩小原始存储块“原地”),则mi将保持指向相同的位置。在这种情况下,通过m查看相同的数据并不奇怪。

P.S.这意味着您的代码的行为是微不足道的undefined。它不能真正用于分析行为是否“适当”。如果记忆确实被释放,你期望会发生什么?

+2

C11标准说(§7.22.3。5):''realloc''函数释放'ptr'指向的旧对象,并返回一个指向size的指定大小的新对象的 指针。 ...如果分配给新对象的内存不能为 ,则旧对象不会被释放并且其值不变。 ...'realloc'函数返回一个指向新对象的指针(它可能与指向旧对象的指针具有相同的 值),或者如果新对象不能被分配为 ,则返回空指针。C99表示相同。 C90并不清楚被释放的旧内存,与C99和C11不同。 –

+0

从以上代码我得到以下输出。(0 0x9a40008 0x9a4000c 0x9a40010 0x9a40014 0x9a40018 0x9a40020 0x9a40024 0x9a40028 0x9a4002c 0x9a40030 米= 0x9a4000c 1 0x9a40038 0x9a4003c 0x9a40040 0x9a40044 0x9a40048 0x9a4004c 0x9a40050 0x9a40054 米= 0x9a4000c 1)与该输出如果realloc的释放旧存储器如何来*米指针能够访问旧存储位置和其存在于旧存储的数据location –

+0

@SumitNaik访问释放的内存会导致*未定义的行为*,这可能以不同的方式表现出来。它可能似乎“看到”旧的价值观。真正的问题在于你甚至在乎的原因。即使你能够以某种方式访问​​释放的内存,“存储”的残留数据也是垃圾。这并不意味着什么。 – AnT

3

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; 
} 

realloc可以做一些更有效的,包括不改变指针,只是让大小分配更大,它可以使用内核设施到别的地方映射内存中,避免复制等等。但总的来说realloc应该被视为正是我上面写的,因为这是最糟糕的情况。

现在,谈到你的程序。你通过无效指针触摸内存,任何事情都可能发生。在致电realloc之后,m停止为有效指针。这并不意味着任何人都不会阻止你使用它,它只是意味着如果你使用它,你的程序不再保证做任何明智的事情。

+1

以蓝色突出显示的'new'! –

+0

@MatteoItalia heh。我想SO上的语法高亮相信C/C++神话。 – Art