realloc() 如何重新分配内存?
How does realloc() reallocate the memory?
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);
尽管名称如此,realloc()
函数并不“重新分配”任何东西。 realloc()
是 而不是 修改内存中现存的对象。相反,它执行某种 "create (new object) & copy the data" 例程。
如果 size
不是 0
并且 ptr
指向一个由内存管理函数之一分配的对象(不仅仅是 malloc()
)或者指向NULL
,然后realloc()
通常 创建一个新对象并将数据从旧对象复制到新对象中。
*我确实说 通常 因为你不能假设内存中的新对象真的被分配了。您必须始终通过检查 returned 指针是否指向 NULL
.
来检查它是否已分配
如果新对象的大小大于旧对象,则新对象超出旧对象大小的字节具有不确定的值。如果新对象比旧对象短,则两者之间的差异内的值将被丢弃。所有其他值都保留在新对象中,就像在旧对象中一样。
The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.
之后,if:
ptr
是 不是 指向 NULL
和 是之前由内存管理函数return编辑的指针,并且此指针指向的对象在调用realloc()
、
之前尚未被释放
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined.
size
不是 0
,
If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
如果 realloc()
没有 return 指向 NULL
,
的指针,则可以真正分配一个新对象
If size is nonzero and memory for the new object is not allocated, the old object is not deallocated
并且实际上仅当 所有 这些前提都满足时,realloc()
释放旧对象的内存并且 return 是一个地址为内存中的新对象。
The realloc function deallocates the old object pointed to by ptr
and returns a pointer to a new object that has the size specified by size
.
如果 realloc()
return 是指向 NULL
的指针,则不会创建新对象,旧对象在内存中的地址保持不变。
可选地,为了使 "pseudo-reallocating" 行为几乎完美,新对象可以在旧对象的释放完成后(如果发生的话)重新分配到存储旧对象的内存。
The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object has not been allocated.
在这种情况下,realloc()
中逻辑上有两次数据复制过程,一次复制到一个缓冲区对象中,然后又回到原来旧对象存储的地方。缓冲区对象在 realloc()
执行完成后被释放。
ptr
的指针首先用于指向旧对象,不应该用于returned指针。如果 realloc()
的调用语句如下所示:
ptr = realloc(ptr,size);
那么如果重新分配失败,通常会发生内存泄漏,因为您只是用空指针覆盖了指向旧内存的指针。如果你没有另一个指向它的指针,你就泄漏了内存。
因此,通常最好使用变体:
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;
请注意,根据我上面所说的,地址可能与调用 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;
}
在我的尝试中,它给出了输出:
value (not address) of ptr1 before realloc(): 0x1db4010
value (not address) of ptr1 after realloc(): 0x1db4010
因此,realloc()
使用后ptr1中存储的地址等同于调用前
补充说明:
当 ptr
是 NULL
指针时,realloc()
充当 malloc()
:
int *ptr = NULL;
size_t length = 4;
ptr = realloc(ptr,sizeof(*ptr) * length);
与
具有相同的效果
int *ptr;
size_t length = 4;
ptr = malloc(sizeof(*ptr) * length);
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
但是,在我个人看来,您不应该首先使用 realloc()
分配动态存储。我建议您始终使用 malloc()
或其他分配内存管理函数。可能会给以后的读者造成一些困难。
- 您不应该使用
realloc(ptr,0)
代替 free(ptr)
来释放动态内存,因为它是由实现定义的,旧对象是否真的被释放。
If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
始终使用 free()
释放动态分配的对象。
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);
尽管名称如此,realloc()
函数并不“重新分配”任何东西。 realloc()
是 而不是 修改内存中现存的对象。相反,它执行某种 "create (new object) & copy the data" 例程。
如果 size
不是 0
并且 ptr
指向一个由内存管理函数之一分配的对象(不仅仅是 malloc()
)或者指向NULL
,然后realloc()
通常 创建一个新对象并将数据从旧对象复制到新对象中。
*我确实说 通常 因为你不能假设内存中的新对象真的被分配了。您必须始终通过检查 returned 指针是否指向 NULL
.
如果新对象的大小大于旧对象,则新对象超出旧对象大小的字节具有不确定的值。如果新对象比旧对象短,则两者之间的差异内的值将被丢弃。所有其他值都保留在新对象中,就像在旧对象中一样。
The contents of the new object shall be the same as that of the old object prior to deallocation, up to the lesser of the new and old sizes. Any bytes in the new object beyond the size of the old object have indeterminate values.
之后,if:
之前尚未被释放ptr
是 不是 指向NULL
和 是之前由内存管理函数return编辑的指针,并且此指针指向的对象在调用realloc()
、If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined.
size
不是0
,If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
如果
的指针,则可以真正分配一个新对象realloc()
没有 return 指向NULL
,If size is nonzero and memory for the new object is not allocated, the old object is not deallocated
并且实际上仅当 所有 这些前提都满足时,realloc()
释放旧对象的内存并且 return 是一个地址为内存中的新对象。
The realloc function deallocates the old object pointed to by
ptr
and returns a pointer to a new object that has the size specified bysize
.
如果 realloc()
return 是指向 NULL
的指针,则不会创建新对象,旧对象在内存中的地址保持不变。
可选地,为了使 "pseudo-reallocating" 行为几乎完美,新对象可以在旧对象的释放完成后(如果发生的话)重新分配到存储旧对象的内存。
The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object has not been allocated.
在这种情况下,realloc()
中逻辑上有两次数据复制过程,一次复制到一个缓冲区对象中,然后又回到原来旧对象存储的地方。缓冲区对象在 realloc()
执行完成后被释放。
ptr
的指针首先用于指向旧对象,不应该用于returned指针。如果 realloc()
的调用语句如下所示:
ptr = realloc(ptr,size);
那么如果重新分配失败,通常会发生内存泄漏,因为您只是用空指针覆盖了指向旧内存的指针。如果你没有另一个指向它的指针,你就泄漏了内存。
因此,通常最好使用变体:
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;
请注意,根据我上面所说的,地址可能与调用 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;
}
在我的尝试中,它给出了输出:
value (not address) of ptr1 before realloc(): 0x1db4010
value (not address) of ptr1 after realloc(): 0x1db4010
因此,realloc()
使用后ptr1中存储的地址等同于调用前
补充说明:
-
当
realloc()
充当malloc()
:
ptr
是 NULL
指针时,int *ptr = NULL;
size_t length = 4;
ptr = realloc(ptr,sizeof(*ptr) * length);
与
具有相同的效果int *ptr;
size_t length = 4;
ptr = malloc(sizeof(*ptr) * length);
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
但是,在我个人看来,您不应该首先使用 realloc()
分配动态存储。我建议您始终使用 malloc()
或其他分配内存管理函数。可能会给以后的读者造成一些困难。
- 您不应该使用
realloc(ptr,0)
代替free(ptr)
来释放动态内存,因为它是由实现定义的,旧对象是否真的被释放。
If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
始终使用 free()
释放动态分配的对象。