Rob*_*rtS 3 c malloc memory-management heap-memory realloc
如何realloc()重新分配首先分配的内存malloc()?
我知道malloc()在重新分配内存之前您需要使用它,但我不明白这应该如何工作。如果动态内存对象的大小减少了realloc()怎么办?调用后是否刚刚删除了该对象的各个部分realloc()?
我的问题是:
realloc()函数如何重新分配由创建的动态内存对象malloc()?
注意:我做了这个问答是因为许多初学者似乎仍然对重新分配内存使用的问题感到困惑,realloc()尽管这里已经存在关于该主题的问题。对于不熟悉该主题但仍不能代表realloc(). 因此,由于问题,恕我直言,仍然不太适合我想要给出的答案,我进行了自己的问答。
注意:以下答案中的所有引用均引自实际的 C 标准,ISO/IEC 9899:2018 (C18),第 7.22.3.4 节。
首先,realloc()ISO/IEC 9899:2018 第 7.22.3 节中的功能概要:
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
Run Code Online (Sandbox Code Playgroud)
尽管它的名字,该realloc()函数不会“重新分配”任何东西。realloc()被不修改存储器中的现存的对象。相反,它执行某种“创建(新对象)和复制数据”例程。
如果size不是0并且ptr指向由内存管理功能之一(不仅仅是malloc())分配的对象或指向NULL,则realloc() 通常会创建一个新对象并将旧对象中的数据复制到新对象中。
*我说通常是因为你不能假设内存中的新对象真的被分配了。您必须始终通过检查返回的指针是否指向 来检查它是否已分配NULL。
如果新对象的大小大于旧对象,则新对象超出旧对象大小的字节具有不确定值。如果新对象比旧对象短,则两者之间的差异内的值将被丢弃。所有其他值都保留在新对象中,就像在旧对象中一样。
新对象的内容应与释放前的旧对象的内容相同,直到新旧大小中较小的一个。新对象中超出旧对象大小的任何字节都具有不确定的值。
之后,如果:
ptr是不是一个指针,NULL 并 为指针早些时候内存管理功能恢复,而这指针指向的对象调用之前一直没有被释放realloc(),
如果 ptr 是空指针,则 realloc 函数的行为类似于指定大小的 malloc 函数。否则,如果 ptr 与之前由内存管理函数返回的指针不匹配,或者如果空间已通过调用 free 或 realloc 函数释放,则行为未定义。
size不是0,
如果大小为零且未分配新对象的内存,则是否释放旧对象由实现定义。如果旧对象未被释放,则其值应保持不变。
如果realloc()没有返回指向 的指针NULL,则可以真正分配一个新对象,
如果 size 非零且未分配新对象的内存,则不会释放旧对象
并且实际上只有当所有这些前提都得到满足时,才会realloc()释放旧对象的内存并返回一个带有新对象在内存中的地址的指针。
realloc 函数释放 指向的旧对象,
ptr并返回一个指向大小由 指定的新对象的指针size。
如果realloc()返回指向 的指针NULL,则不会创建新对象并且旧对象在其内存地址处保持不变。
可选地,为了使“伪重新分配”行为几乎完美,新对象可能会在旧对象的释放完成后(如果发生)重新分配回旧对象所在的内存地址被存储。
realloc 函数返回一个指向新对象的指针(可能与指向旧对象的指针具有相同的值),如果新对象尚未分配,则返回空指针。
在这种情况下,在逻辑上有两个数据复制过程realloc(),一次进入缓冲区对象,然后返回到存储原始旧对象的位置。缓冲区对象在 的执行realloc()完成后被释放。
的指针ptr,其第一被用于指向旧对象不应该用于返回的指针。如果调用语句realloc()如下所示:
ptr = realloc(ptr,size);
Run Code Online (Sandbox Code Playgroud)
那么如果重新分配失败,通常会发生内存泄漏,因为您只是用空指针覆盖了指向旧内存的指针。如果你没有另一个指向它的指针,你就泄露了内存。
因此,通常最好在以下情况下使用变体:
void *new_space = realloc(ptr, new_size);
if (new_space == NULL)
{
/* …handle out of memory condition… */
/* ptr is still valid and points to the previously allocated data */
return; /* Or otherwise do not continue to the following code */
}
ptr = new_space;
size = new_size;
Run Code Online (Sandbox Code Playgroud)
请注意,根据我上面所说的,地址可能与调用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!\n");
return 1;
}
printf("value (not address) of ptr1 before realloc(): %p\n", (void *)ptr1);
ptr1 = realloc(ptr1,length2);
if(ptr1 == NULL)
{
printf("No new object allocated. Old object remains!\n");
return 1;
}
printf("value (not address) of ptr1 after realloc(): %p\n", (void *)ptr1);
free(ptr1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我的尝试中,它给出了以下输出:
value (not address) of ptr1 before realloc(): 0x1db4010
value (not address) of ptr1 after realloc(): 0x1db4010
Run Code Online (Sandbox Code Playgroud)
所以,ptr1 中存储的地址在使用之后realloc()就相当于调用之前。
realloc()充当malloc()whenptr是一个NULL指针:void *new_space = realloc(ptr, new_size);
if (new_space == NULL)
{
/* …handle out of memory condition… */
/* ptr is still valid and points to the previously allocated data */
return; /* Or otherwise do not continue to the following code */
}
ptr = new_space;
size = new_size;
Run Code Online (Sandbox Code Playgroud)
将具有相同的效果,
#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!\n");
return 1;
}
printf("value (not address) of ptr1 before realloc(): %p\n", (void *)ptr1);
ptr1 = realloc(ptr1,length2);
if(ptr1 == NULL)
{
printf("No new object allocated. Old object remains!\n");
return 1;
}
printf("value (not address) of ptr1 after realloc(): %p\n", (void *)ptr1);
free(ptr1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果 ptr 是空指针,则 realloc 函数的行为类似于指定大小的 malloc 函数。
但是,在我个人看来,您不应该首先使用realloc(). 我建议您始终使用malloc()或 其他分配内存管理功能。这可能会给未来的读者带来一些困难。
realloc(ptr,0)作为替代free(ptr)来释放动态内存,因为它是实现定义的,无论旧对象是否真的被释放。如果大小为零且未分配新对象的内存,则是否释放旧对象由实现定义。如果旧对象未被释放,则其值应保持不变。
始终用于free()释放动态分配的对象。
| 归档时间: |
|
| 查看次数: |
1317 次 |
| 最近记录: |