【问题标题】:Does realloc overwrite old contents?realloc 会覆盖旧内容吗?
【发布时间】:2011-04-20 12:40:28
【问题描述】:

当我们通过realloc()重新分配内存时,之前的内容会被覆盖吗?我正在尝试制作一个程序,每次我们将数据输入到其中时都会重新分配内存。

请告诉我有关通过 realloc 分配内存的情况,例如它是否依赖于编译器?

【问题讨论】:

    标签: c realloc


    【解决方案1】:

    不用担心旧内容。

    使用realloc 的正确方法是使用特定指针进行重新分配,测试该指针,如果一切正常,更改旧指针

    int *oldpointer = malloc(100);
    
    /* ... */
    
    int *newpointer = realloc(oldpointer, 1000);
    if (newpointer == NULL) {
        /* problems!!!!                                 */
        /* tell the user to stop playing DOOM and retry */
        /* or free(oldpointer) and abort, or whatever   */
    } else {
        /* everything ok                                                                 */
        /* `newpointer` now points to a new memory block with the contents of oldpointer */
        /* `oldpointer` points to an invalid address                                     */
        oldpointer = newpointer;
        /* oldpointer points to the correct address                                */
        /* the contents at oldpointer have been copied while realloc did its thing */
        /* if the new size is smaller than the old size, some data was lost        */
    }
    
    /* ... */
    
    /* don't forget to `free(oldpointer);` at some time */
    

    【讨论】:

    • oldpointer = newpointer; 之后应该释放newpointer 还是我必须保留它?
    • oldpointer = newpointer; 之后,两个指针都指向同一个内存区域。执行free(newpointer);free(oldpointer); 相同。你不想以任何方式惹newpointer:忘记它的存在。
    • 假设 oldpointer 指向一个内存块,其 address: 0xaaaaaa 在执行 this: int *newpointer = realloc(oldpointer, 1000); , realloc如果可能,将尝试将内存分配给同一块,否则它将搜索另一个内存块(当然比旧的更大)。假设新区块位于 address: 0xbbbbbb。现在成功重新分配内存后,address: 0xaaaaaa 及其内容会发生什么。 realloc 是否在成功重新分配内存时在旧内存块上调用 free()
    • @barnes: 是的,当realloc()“工作”时,它会自动执行相当于在旧内存块上调用free();见C11 7.22.3.5 "realloc 函数释放旧对象...".
    • 谢谢你的链接,伙计。 :)
    【解决方案2】:

    它在不覆盖现有内容的情况下增长已经分配的内存,或者(如果它无法增长)它在不同的位置分配新的更大的内存并将现有内容从以前的内存复制到新的内存中。

    【讨论】:

    • realloc 返回一个新的指针值,它的值可能与旧指针值相同也可能不同,您应该使用它来覆盖以前的指针值:例如ptr = realloc(ptr, new_size);
    • 如果 realloc 失败,你的 ptr 指向 NULL 并且旧的 ptr 会丢失(阅读 memory leak
    • @pmg 你是对的。我刚刚对your answer 做了+1,这是覆盖现有指针的更谨慎的版本。
    【解决方案3】:

    您应该像旧指针被覆盖一样进行编程,是的。旧内存不再分配,因此可以由程序的另一部分(或系统线程)重新分配,并在您调用 realloc 后随时重写。

    虽然新内存将始终包含与旧内存中相同的数据(如果需要,它会为您复制),但仅限于旧块的大小,最后分配的任何额外空间都将是未初始化。

    如果你想要一个副本,那就做一个新的 malloc 并使用 memcpy。

    在实现方面,当您调用 realloc 来增加大小时,可能会发生以下情况之一:

    • 分配新块并复制旧内存的内容,释放旧块,返回新指针。
    • 如果块后的区域没有分配,现有的块可能会被扩展并返回相同的指针。

    由于您无法知道发生了什么,或者即使使用了与上面建议的完全不同的实现,您应该始终根据 realloc 的规范进行编码,即您不能使用任何旧指针更多,您必须使用新的。

    【讨论】:

    • 你好,10 年后)你说:“分配了一个新块,复制了旧内存的内容,释放了旧块,返回了新指针”。那么,如果我使用相同的指针:p = realloc(p, ...),是否意味着旧内存将被释放?我会丢失数据吗?
    • 不,在释放旧块之前,数据将被复制到返回的p 指向的新块中。这一切都发生在realloc 返回之前,因此新的p 仍然指向您的数据。
    【解决方案4】:

    很难说你在问什么,但如果你问是否可以在传递给realloc 的旧地址读取“旧内容”,答案是不能。在某些情况下,您可能会在那里找到部分或全部旧内容,但除非 realloc 返回您传递给它的相同指针,否则对旧指针的任何使用都是未定义行为

    如果您只是询问是否将旧内容保留在realloc 返回的新地址中,答案是肯定的(直到旧大小和新大小的最小值)。

    【讨论】:

      猜你喜欢
      • 2012-05-30
      • 2012-11-01
      • 1970-01-01
      • 2019-10-05
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      • 2015-12-22
      相关资源
      最近更新 更多