realloc()如何重新分配内存? [英] How does realloc() reallocate the memory?

查看:217
本文介绍了realloc()如何重新分配内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How does realloc() reallocate the memory which was first allocated by malloc()?

我知道您必须先使用malloc(),然后才能重新分配内存,但是我不知道该怎么办.如果动态内存对象的大小减小了realloc()怎么办?调用realloc()之后,这些对象的各个对象是否刚刚被擦除?

I know that you need to use malloc() before you´re able to reallocate the memory, but I don´t understand how that really should work. What if a dynamic-memory object gets decreased in size by realloc()? Is this respective piece of the object just erased after the call to realloc()?

我的问题是:

  1. realloc()函数如何重新分配由malloc()创建的动态内存对象?
  1. How does the realloc() function reallocate a dynamic-memory object created by malloc()?

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

Note: I did this Q&A because many beginners seem to be still confused about the issue of reallocating memory using realloc() despite already existing questions here on SO for that topic. They seem to be a little confusing for anyone who is new to the topic and still do not represent the whole behavior of realloc(). Therefore, and because the questions, IMHO, still do not quite fit the answer I´d want to give, I made my own Q&A.

推荐答案

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

首先,ISO/IEC 9899:2018第7.22.3节中realloc()函数的提要:

First, the synopsis for the realloc() function from ISO/IEC 9899:2018, Section 7.22.3:

#include <stdlib.h> 
void *realloc(void *ptr, size_t size);


尽管其名称,但realloc()函数不会" re 分配"任何内容. realloc()不是不是修改内存中的现有对象.相反,它执行某种创建(新对象)并复制数据"例程.


Despite its name, the realloc() function does not "reallocate" anything. realloc() is not modifying an extant object in memory. Instead, it does some sort of "create (new object) & copy the data" routine.

如果size不是0,并且ptr要么指向由内存管理功能之一分配的对象(不仅限于malloc()),要么指向NULL,则realloc() 通常创建一个新对象并将数据从旧对象复制到新对象中.

If size is not 0 and ptr either points to an object that was allocated by one of the memory management functions (not just malloc() only) or points to NULL, then realloc() usually creates a new object and copies the data from the old object into the new object.

*我通常会说 ,因为您不能假设内存中确实分配了一个新对象.您必须始终通过检查返回的指针是否指向NULL来检查它是否已分配.

*I do say usually because you can´t assume that a new object in memory is really allocated. You must always check whether or not it was allocated by checking whether the returned pointer points to NULL.

如果新对象的大小大于旧对象的大小,则超出旧对象大小的新对象的字节将具有不确定的值.如果新对象比旧对象短,则它们之间的差之内的值将被丢弃.其他所有值都保留在新对象中,就像在旧对象中一样.

If the size of the new object is larger than the old object, the bytes of the new object that are beyond the size of the old object have indeterminate values. If the new object is shorter than the old object, the values inside the difference between are thrown away. Every other value remains in the new object as it was in the old one.

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

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.


之后,如果:

  • ptr not 指向NULL 的指针, 先前由内存管理功能返回的指针,并且该指针所指向的对象在调用realloc()

  • ptr is not a pointer to NULL and is a pointer earlier returned by a memory management function, and the object this pointer is pointing to has not been deallocated before the call to realloc(),

如果ptr是空指针,则对于指定的大小,realloc函数的行为类似于malloc函数.否则,如果ptr与内存管理函数先前返回的指针不匹配,或者如果通过调用free或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

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

    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()没有返回指向NULL的指针,则确实可以分配一个新对象,

  • and a new object could really be allocated if realloc() did not return a pointer to NULL,

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

    If size is nonzero and memory for the new object is not allocated, the old object is not deallocated

  • 并且实际上只有在满足所有前提的情况下,realloc()才会释放旧对象的内存,并返回一个包含新对象地址的指针.

    and really only if all of these premises are fulfilled, realloc() deallocates the memory of the old object and returns a pointer with the address of the new object in memory.

    realloc函数取消分配由ptr指向的旧对象,并返回指向具有由size指定的大小的新对象的指针.

    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()返回指向NULL的指针,则不会创建新对象,并且旧对象在内存中的地址保持不变.

    If realloc() returns a pointer to NULL, no new object is created and the old object remains unchanged at its address in memory.

    (可选)为使伪重新分配"行为近乎完美,可以在完成旧对象的重新分配(如果发生)之后将新对象分配回内存中的同一地址,其中旧对象已存储.

    Optionally, to make the "pseudo-reallocating" behavior almost perfect, it is possible that the new object, after the deallocation of the old object is done (if it happens), is allocated back at the same address in memory where the old object was stored.

    realloc函数返回指向新对象的指针(该值可能与指向旧对象的指针的值相同),如果未分配新对象,则返回null指针.

    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()的执行完成后,将释放缓冲区对象.

    In this case, there are logically two data copying processes in realloc(), one time into a buffer object and later back to the place of where the original old object was stored. The buffer object is deallocated after the execution of realloc()is completed.

    首先用于指向旧对象的ptr指针不应用于返回的指针.如果对realloc()的调用语句如下所示:

    The pointer of ptr which first is used for pointing to the old object should not be used for the returned pointer. If the call statement to realloc() looks like this:

    ptr = realloc(ptr,size);
    

    然后,如果重新分配失败,通常会发生内存泄漏,因为您只是使用空指针重写了指向旧内存的指针.如果没有其他指向它的指针,则说明内存泄漏了.

    then you usually have a memory leak if the reallocation fails because you just overwrote the pointer to the old memory with a null pointer. If you don't have another pointer that points to it, you've leaked the memory.

    因此,通常最好在以下位置使用变体:

    Therefore, it is usually better to use a variant on:

    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()之前的地址相同.

    Note that according to what I´ve said above, the address may be the same as before the call to realloc().

    为确保内存管理确实以这种方式发生,我们可以尝试以下实验:

    To make sure that memory management is really happening that way, we can try this experiment:

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

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

    At my try it gave the output of:

    value (not address) of ptr1 before realloc(): 0x1db4010
    value (not address) of ptr1 after realloc(): 0x1db4010
    

    因此,使用realloc()之后存储在ptr1中的地址等于调用它之前的地址.

    So, the address stored in ptr1 after the use of realloc() is equivalent to before the call of it.

      ptrNULL指针时,
    • realloc()充当malloc():
    • realloc() acts as malloc() when ptr is a NULL pointer:
    int *ptr = NULL;
    size_t length = 4;
    ptr = realloc(ptr,sizeof(*ptr) * length);
    

    应具有与

    int *ptr;
    size_t length = 4;
    ptr = malloc(sizeof(*ptr) * length);
    

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

    If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.

    但是,我个人认为,您不应该首先使用realloc()分配动态存储.我建议您始终使用malloc()或其他分配内存管理功能.这可能会给将来的读者带来一些麻烦.

    But, in my personal opinion, you should not first allocate dynamic storage by the use of realloc(). I recommend that you always use malloc() or another allocating memory management function instead. It may cause some difficulties to future readers.

    • 您不应使用realloc(ptr,0)代替free(ptr)来取消分配动态内存,因为无论是否真的取消分配了旧对象,它都是实现定义的.
    • You should not use realloc(ptr,0) as substitution for free(ptr) to deallocate the dynamic memory because it is implementation-defined whether the old object is really deallocated or not.

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

    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()取消分配动态分配的对象.

    Always use free() to deallocate a dynamically allocated object.

    这篇关于realloc()如何重新分配内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆