【问题标题】:realloc() unable to reallocate memoryrealloc() 无法重新分配内存
【发布时间】:2014-03-29 09:33:33
【问题描述】:

我正在编写一个文件复制程序,在该程序中我遇到了关于 realloc() 的困难。 请看下面的 sn-p(我写它是为了理解 realloc() 的工作原理):-

int main(){
    char *p =(char *) malloc ( 10 ),*t;
    p = "this is";
    if (strlen (p)==7)
    {
        t = realloc ( p,14);
        if ( t==NULL)
        {
            printf ("no no\n");
        }
    }
    printf("%p\n%p\n%d",p,t,strlen(p));
    free (p);
    free (t);
    return 1;
}

输出

no no      //because realloc () is unable to reallocate  the memory
00450357   //address of p
00000000   //address of t

那么为什么 realloc() 无法重新分配内存并将其(其地址)分配给t

编辑 我在 Windows 中使用代码块。

【问题讨论】:

  • 因为你已经用字符串赋值破坏了 malloc 返回的地址。如果你使用了 strcpy,那么 realloc 会起作用,但你会在 free(p) 上获得双重释放,因为它已经在 realloc 期间被释放。

标签: c realloc


【解决方案1】:

您已经用静态字符串的地址覆盖了 malloc 返回的值。然后realloc接收静态字符串的地址作为参数重新分配。

char *p =(char *) malloc ( 10 ),*t;
p = "this is";
t = realloc ( p,14);

你可能想要的是:

char *p =(char *) malloc ( 10 ),*t;
strcpy(p, "this is");
t = realloc ( p,14);

【讨论】:

  • 它是否被覆盖,因为它的(字符串文字)类型为 const char *
  • 语句p = "this is"; 表示内存中的某处(肯定不在堆上)字符串“this is”,其地址分配给p。字符串由编译器在编译时创建,它通常位于为从程序代码中获取的常量保留的内存部分。
  • 如果我们使用整数数组,那么大小写会不同吗?不是吗?
  • 不确定是否理解整数数组的要点。关键是您必须使用从malloc 获得的指针调用realloc。在您的情况下,您从 malloc 获得了一个指针,但随后又获得了另一个指针(并将其分配给 p)并用这个不同的指针调用了 realloc
  • 因为我已经为 p 和 t 编写了 free()(在程序末尾)。如果我只为 t 编写它可以吗?
【解决方案2】:

分配给p之后你正在做

p = "this is";

覆盖malloc() 返回的值。由于p 指向的内存不可释放,realloc() 会失败。

复制字符串做

strcpy(p, "this is");

虽然检查p有足够的内存分配,否则使用

strncpy(p, "this is", length_of_p);

【讨论】:

  • 但是如果我们有整数类型的指针来存储 malloc 返回的指针,并且我们使用循环将值存储在该地址作为 *p++=2。那么它也是可重新分配的,为什么这里不是呢?
【解决方案3】:

realloc 的手册页指出,除非realloc 的第一个参数是NULL,否则它一定是由先前对malloccallocrealloc 的调用返回的。

t = realloc (p, 14);

上面的语句将p 传递给realloc,它指向字符串文字"this is",它具有静态存储持续时间并且是只读的,尽管没有const 限定。因此,您的程序调用了未定义的行为。(由于段错误,它在我的机器上崩溃了。)

此外,当您重新分配 p 字符串字面量的第一个元素的地址时,您会失去对动态分配内存的处理,从而导致内存泄漏。

char *p =(char *) malloc ( 10 ),*t;
p = "this is";

您实际需要做的是使用strcpy 将字符串文字的内容复制到动态分配的缓冲区。

// include the required headers

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// explicitly state void in the parameter list of main
int main(void) {
    // do not cast the result of malloc
    char *p = malloc(10 * sizeof *p);
    char *t;
    if(p == NULL) {
        printf("malloc failed\n");
        return 1;
    }
    // beware of buffer overrun by strcpy
    // consider using the safer strncpy if it suits
    p = strcpy(p, "this is");
    if(strlen(p) == 7) {
        // save the result of realloc in t
        // in case, realloc fails to allocate
        t = realloc(p, 14);
        if(t == NULL) {
            printf("realloc failed\n");
            // handle it
            // p points to old buffer
        }
        else {
            t = NULL;
            // p points to new buffer
        }
    }

    // after your done with p, free it
    free(p);

    return 0;
}

【讨论】:

  • 如果我写 t=realloc ( p,14 ) 这是否意味着 p 将被释放并且 t 指向相同的起始地址但它的范围增加了?
  • @Bayant_singh 否。如果realloc 成功,则返回与p 相同的值。在这里,我们将realloc 的结果存储在t 中,因为如果realloc 失败,那么它将保持p 不变并返回NULL。因此,如果realloc 失败,执行p = realloc(p, 14); 会丢失旧缓冲区的句柄导致内存泄漏。
  • @Bayant_singh 另外,请注意,如果realloc 可以扩展旧缓冲区,那么它将。如果不能,则分配新缓冲区,将旧缓冲区复制到新缓冲区,然后释放旧缓冲区。因此,在调用成功的情况下,realloc 的返回值可能相同也可能不同。详情请阅读手册页man7.org/linux/man-pages/man3/malloc.3.html
  • 但是如何将旧缓冲区复制到新缓冲区?
  • @Bayant_singh realloc 为您完成。这就是它的用途。当realloc 分配内存时,它会保留旧数据。
猜你喜欢
  • 2015-03-22
  • 2020-05-01
  • 2020-01-31
  • 2018-11-10
  • 1970-01-01
  • 2021-03-16
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
相关资源
最近更新 更多