首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在不丢弃旧记忆的情况下使用realloc函数

如何在不丢弃旧记忆的情况下使用realloc函数
EN

Stack Overflow用户
提问于 2020-10-12 00:18:05
回答 3查看 203关注 0票数 0

首先,我为我糟糕的英语感到抱歉。

我对C语言中的“realloc”函数有一个疑问。我认为它用给定的长度分配记忆。当内存对给定长度不够时,它将整个内存复制到另一个内存指针并返回它。

我想用realloc函数来保存旧的记忆。所以我判了另一个指针,让它指向过去的记忆。但是,每当“realloc”函数起作用时,它就会释放旧的记忆。我怎样才能保存旧的记忆?另外,我想知道为什么会这样。

下面是用于测试realloc函数的代码及其结果。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

int* ptr1, lenPtr1;
int* ptr2;

void double_ptr1(){
    lenPtr1 *= 2;
    ptr1 = (int*)realloc(ptr1, sizeof(int) * lenPtr1);
}

void print(){
    printf("ptr1 -> %p, *ptr1 = %d\n", ptr1, *ptr1);
    printf("ptr2 -> %p, *ptr2 = %d\n", ptr2, *ptr2);
    printf("\n");
}

int main(){
    lenPtr1 = 10;
    ptr1 = (int*)malloc(sizeof(int) * lenPtr1);
    ptr2 = ptr1;
    *ptr1 = 10;

    print();
    double_ptr1();
    print();

    system("pause");
    return 0;
}

ptr1 -> 0108D2F0,*ptr1 = 10 ptr2 -> 0108D2F0,*ptr2 = 10

ptr1 -> 00FF5740,*ptr1 = 10 ptr2 -> 0108D2F0,*ptr2 = -17891602

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-10-12 00:50:16

一个包含注释中建议的所有改进并避免使用全局变量的示例,并在程序退出之前释放所有分配的内存。只需要将终端窗口打开在窗口上,因此有条件地将system("pause");括起来。

总之,你应该有:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int *double_ptr (int *ptr, int *ptrsz)      /* pass needed information as parameters */
{
    int *newptr = malloc (2 * *ptrsz * sizeof *newptr); /* allocate new block of mem */
    
    if (newptr) {                                       /* validate allocation */
        memcpy (newptr, ptr, *ptrsz * sizeof *ptr);     /* copy to new block of mem */
        *ptrsz *= 2;                                    /* update allocated size */
    }
    
    return newptr;      /* return pointer */
}

void print (int *ptr1, int *ptr2)           /* pass needed information as parameters */
{
    /* only one call to printf required */
    printf ("ptr1 -> %p, *ptr1 = %d\nptr2 -> %p, *ptr2 = %d\n\n",
            (void*)ptr1, *ptr1, (void*)ptr2, *ptr2);
}

int main (void) {
    
    int *ptr1 = NULL, *ptr2 = NULL, lenPtr1 = 10;       /* avoid global variables */

    if (!(ptr1 = malloc (lenPtr1 * sizeof *ptr1))) {    /* validate EVERY allocation */
        perror ("malloc-ptr");
        return 1;
    }
    ptr2 = ptr1;    /* pointer 1 and 2 hold same address where 10 is stored in memory */
    *ptr1 = 10;

    printf ("lenPtr1: %d\n", lenPtr1);                  /* output len, addresses, values */
    print (ptr1, ptr2);
    
    if (!(ptr1 = double_ptr (ptr1, &lenPtr1))) {        /* double size of ptr1 */
        perror ("malloc-double-ptr1");
        return 1;
    }
    
    printf ("lenPtr1: %d\n", lenPtr1);                  /* output len, addresses, values */
    print (ptr1, ptr2);
    
    free (ptr1);                                        /* free allcoated memory */
    free (ptr2);
    
#if defined (_WIN32) || defined (_WIN64)
    system("pause");
#endif
}

示例使用/输出

代码语言:javascript
复制
$ ./bin/doubleptrsz
lenPtr1: 10
ptr1 -> 0xb18260, *ptr1 = 10
ptr2 -> 0xb18260, *ptr2 = 10

lenPtr1: 20
ptr1 -> 0xb186a0, *ptr1 = 10
ptr2 -> 0xb18260, *ptr2 = 10

如果你还有其他问题,请告诉我。

票数 1
EN

Stack Overflow用户

发布于 2020-10-12 00:27:02

当您实际指定由ptr2指向的原始指针时,原始指针的地址将被移除。

因此,在您重新分配ptr1之后,ptr2点地址就不再存在了。

如果您想要保留旧内存,那么您只需要将malloc(或calloc)新内存保留到ptr1,而不需要realloc原始内存。

票数 1
EN

Stack Overflow用户

发布于 2020-10-12 01:08:39

当内存对给定长度不够时,它将整个内存复制到另一个内存指针并返回它。

不完全是。realloc 总是释放旧内存。它可能返回相同的指针。

C11 7.20.3.4 realloc.

realloc函数释放ptr指向的旧对象,并返回指向具有size指定大小的新对象的指针.realloc函数返回指向新对象的指针(该对象的值可能与指向旧对象的指针相同)。

我想用realloc函数来保存旧的记忆。

你不能这么做。

如果您需要更多的内存,malloc是一个新内存块,而不是重新分配旧内存。

如果要缩小内存,请继续按原样使用内存。一切都会好的,这只是在浪费记忆。

我都不推荐。相反,重新设计您正在做的任何操作,以便间接访问指针。也许使用指向指针的指针。或者将指针放入结构中,并传递指向该结构的指针。

或者,重新设计它,这样你就不需要再现实了。例如,当从文件读取时,使用固定大小的缓冲区读取行,然后以足够的空间将其复制到内存中。

代码语言:javascript
复制
// A large buffer to reuse for each line.
char buf[BUFSIZ];

while( fgets(buf, sizeof(buf), fp) ) {
  // Allocate exactly enough space for the line.
  // In reality, use strdup.
  char *string = malloc(strlen(buf) + 1);
  strcpy(string, buf);
}

或者更改为不依赖于单个内存块的数据结构。例如,链表而不是数组。

此外,我想知道为何会出现这种情况。

malloc有许多实现。,但它们都必须分配没有重叠的连续内存块。

考虑两个对malloc的调用。

代码语言:javascript
复制
char *foo = malloc(8);
char *bar = malloc(8);

假设foo和bar被分配给相邻的内存块,如下所示。(注:不能保证它们会相邻,而且有很多理由不能保证它们是相邻的。)

代码语言:javascript
复制
0123456789abcdef0123456789abcdef
^^^^^^^^
|       ^^^^^^^^
foo     |
        bar

现在你试着长胖了。

代码语言:javascript
复制
foo = realloc(foo, 16);

如果realloc试图保持相同的指针,foo将不得不重叠到bar的内存中。

代码语言:javascript
复制
0123456789abcdef0123456789abcdef
^^^^^^^^^^^^^^^^
|       ^^^^^^^^
foo     |
        bar

这是不允许的,分配不能重叠。它们也必须是连续的,因此它不能这样做:

代码语言:javascript
复制
0123456789abcdef0123456789abcdef
^^^^^^^^        ^^^^^^^^
|       ^^^^^^^^
foo     |
        bar

如果允许它这样做,指针数学就不能工作。您将无法可靠地添加到foo以遍历其分配的内存。

因此realloc必须释放foo并分配一个新块。(同样,也不能保证分配到哪里。)

代码语言:javascript
复制
0123456789abcdef0123456789abcdef
        ^^^^^^^^
        |       ^^^^^^^^^^^^^^^^
        bar     |
                foo
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64310236

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档