realloc()如何重新分配内存?

问题描述 投票:0回答:1

realloc()如何重新分配由malloc()首先分配的内存?

[我知道,您需要先使用malloc(),然后才能重新分配内存,但是我不知道它应该如何工作以及如果动态内存对象的大小减小了[ C0]?是在调用realloc()之后刚刚擦除的各个对象吗?


我的问题是:

  1. realloc()函数如何重新分配由realloc()创建的动态内存对象?

注:我进行了此问题与解答,因为许多初学者似乎仍然对使用malloc()重新分配内存的问题感到困惑,尽管此处已经存在关于该主题的问题。对于刚接触该主题但仍不代表realloc()整个行为的任何人,它们似乎有些困惑。因此,也是我的原因,恕我直言,这些问题仍不完全符合我想要给出的答案,我进行了自己的问答。

c memory-management malloc realloc
1个回答
0
投票

注:以下答案中的所有引用均来自实际的C标准,ISO / IEC 9899:2018(C18),第7.23.2.4节。


首先,来自ISO / IEC 9899:2018,第7.22.3.4节的realloc()功能的提要:

realloc()

尽管有其名称,#include <stdlib.h> void *realloc(void *ptr, size_t size); 函数不会“ re分配”任何内容。 realloc()not修改内存中的现有对象。相反,它执行某种“创建(新对象)并复制数据”例程。


[如果realloc()的指针必须指向一个对象,该指针首先由任何一个内存管理功能(不仅限于ptr分配),要么指向malloc(),并且NULL为通常不是size0创建一个新对象并将realloc()指向的旧对象的数据复制到该新对象中。

**我确实说通常,因为您不能假设实际上已经分配了一个内存中的新对象。如果指向ptr,则始终必须通过证明返回的指针来检查它是否已分配。


如果新对象的大小大于旧对象,则新对象中超出旧对象大小的部分具有不确定的值。如果新对象短于旧对象,则两者之间的差之内的值将被丢弃。

新对象的内容应与重新分配之前的旧对象相同,直到新旧大小中的较小者为止。新对象中超出旧对象大小的任何字节都具有不确定的值。


此后,

If

  • NULLnot指向ptr的指针,并且is之前由其所指向的对象的内存管理函数返回的指针,直到调用NULL时才释放(或至少指向以前以这种方式分配的对象,直到realloc()调用时才释放)

    如果ptr是空指针,则对于指定的大小,realloc函数的行为类似于malloc函数。否则,如果ptr与内存管理函数先前返回的指针不匹配,或者如果通过调用free或realloc函数已经释放了空间,则该行为是不确定的。

  • [realloc()不是size

  • 如果size为零,并且未分配新对象的内存,则是否释放旧对象由实现定义。如果旧对象未释放,则其值应保持不变。

  • 并且可以真正分配一个新对象/ 0没有返回指向realloc()的指针,

  • 如果大小为非零并且未分配新对象的内存,则不会释放旧对象

    并且仅当满足这些前提的[[all

时,NULL才释放旧对象的内存并返回带有新对象地址的指针在内存中。
realloc函数将分配由realloc()指向的旧对象,并返回指向具有由ptr指定的大小的新对象的指针。

如果size返回指向realloc()的指针,则不会创建任何新对象,并且旧对象在内存中的地址保持不变。


[可选,为了使“伪重新分配”行为几乎完美,有可能在完成旧对象的重新分配(如果发生)后,将新对象分配给与内存相同的地址。旧对象已存储。

realloc函数返回一个指向新对象的指针(该值可能与指向旧对象的指针的值相同;如果未分配新对象,则返回一个空指针。

在这种情况下,NULL中发生了两个数据复制过程。一次进入缓冲对象,然后又回到原始的旧对象的位置。 realloc()的执行完成后,将释放缓冲区对象。


realloc()的指针首先用于指向旧对象,也可以用于返回的指针。然后,对ptr的调用语句将如下所示:

realloc()

从技术上讲,ptr = realloc(ptr,size);
只是在这种情况下修改realloc()内部的地址值,从旧对象的地址更改为新对象的地址。请注意,根据我上面所述,地址可能与调用ptr之前的地址相同。


为了确保确实以这种方式进行内存管理,我们尝试以下实验:

realloc()

在我的尝试下,它给出了输出:

#include <stdio.h> #include <stdlib.h> int main(void) { size_t length1 = 4; size_t length2 = 2; int *ptr1 = malloc(sizeof(*ptr1) * length1); if(ptr1 == NULL) { printf("The object could not be allocated!"); return 1; } printf("value (not address) of ptr1 before realloc(): %p\n",ptr1); ptr1 = realloc(ptr1,length2); if(ptr1 == NULL) { printf("No new object allocated. Old object remains!"); return 1; } printf("value (not address) of ptr1 after realloc(): %p\n",ptr1); return 0; }

因此,在使用value (not address) of ptr1 before realloc(): 0x1db4010
value (not address) of ptr1 after realloc(): 0x1db4010
之后存储在ptr1中的地址等于调用它之前的地址。

附加说明:

    realloc()
  • 可以

realloc()malloc()指针时充当ptr
NULL
与具有相同的作用,

int *ptr = NULL; size_t length = 4; ptr = realloc(ptr,sizeof(*ptr) * length);

如果ptr是空指针,则对于指定的大小,realloc函数的行为类似于malloc函数。

但是您不应该首先使用int *ptr; size_t length = 4; ptr = malloc(sizeof(*ptr) * length); 分配动态存储。始终使用realloc()


    您不应该使用malloc()代替realloc(ptr,0)来释放动态内存存储,因为它由实现来定义对象是否真正释放。
  • 如果size为零,并且未分配新对象的内存,则是否释放旧对象由实现定义。如果旧对象未释放,则其值应保持不变。

始终使用free(ptr)释放动态分配的对象。

© www.soinside.com 2019 - 2024. All rights reserved.