realloc() 无效的旧大小

Posted

技术标签:

【中文标题】realloc() 无效的旧大小【英文标题】:realloc() invalid old size 【发布时间】:2014-08-26 02:41:08 【问题描述】:

我正在从 KandR C 编程书中做一个有趣的练习。该程序用于从用户输入的一组行中找到最长的行,然后将其打印出来。

这是我写的(部分是直接从书中摘录的):-

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

int MAXLINE =  10;
int INCREMENT = 10;

void copy(char longest[], char line[])
    int i=0;

    while((longest[i] = line[i]) != '\0')
        ++i;
    


int _getline(char s[])
    int i,c;

    for(i=0; ((c=getchar())!=EOF && c!='\n'); i++)
        if(i == MAXLINE - 1)
            s = (char*)realloc(s,MAXLINE + INCREMENT);

            if(s == NULL)
                printf("%s","Unable to allocate memory");
                //  goto ADDNULL;
                exit(1);
            

            MAXLINE = MAXLINE + INCREMENT;
        
        s[i] = c;
    

    if(c == '\n')
        s[i] = c;
        ++i;
    

ADDNULL:
    s[i]= '\0';
    return i;
 

int main()
    int max=0, len;

    char line[MAXLINE], longest[MAXLINE];

    while((len = _getline(line)) > 0)
        printf("%d", MAXLINE);
        if(len > max)
            max = len;
            copy(longest, line);
        
    

    if(max>0)
        printf("%s",longest);
    

    return 0;

在一行输入超过10个字符的那一刻,程序崩溃并显示:-

*** Error in `./a.out': realloc(): invalid old size: 0x00007fff26502ed0 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3d6a07bbe7]
/lib64/libc.so.6[0x3d6a07f177]
/lib64/libc.so.6(realloc+0xd2)[0x3d6a0805a2]
./a.out[0x400697]
./a.out[0x40083c]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x3d6a021b45]
./a.out[0x400549]

我还检查了realloc invalid old size,但无法遵循将指针传递给指向修改数组的函数的指针的逻辑。

【问题讨论】:

程序中的其他错误(使用括号确保计算和其他地方的含义)程序正在将 'int' 大小值写入 's' 数组,但仅分配 char 大小增量。跨度> 函数名'_getline'会与C库函数名冲突。而是使用类似“myGetLine”的东西 传递给 _getline 的参数不是指向 malloc 区域的指针,而是堆栈上区域的第一个地址。因此,尝试重新分配()该指针是错误的。建议获取 _getline 参数的初始指针为“line = (MAXSIZE*sizeof(int));” 执行realloc时,使用第二个参数((MAXLINE + INCREMENT)*sizeof(int)) 【参考方案1】:

realloc 调用将通过获取指向heap 上存储区域的指针来重新分配内存,即调用malloc 的动态分配内存结果。

在您的情况下,问题是您在stack 上分配内存,而不是通过调用malloc 动态分配内存,从而导致heap 上的内存分配。并且,将automatic 字符数组line 的指针传递给_getline,后者使用它来调用realloc。所以,你得到了错误。

尝试动态分配字符数组line

char* line  = (char *) malloc(MAXLINE); 
char* longest = ( char *) malloc(MAXLINE);

【讨论】:

那么我的 _getline 函数将类似于 _getline(char* s)? @Karan,不要保持_getline 原样,在C 数组中names 自动decayed 指向指向它们的第一个元素的指针。 @Karan,请参阅***.com/questions/1461432/what-is-array-decaying 了解数组衰减。 谢谢。但是,在大输入时,我得到另一个与 realloc 相关的错误:*** `./a.out' 中的错误:realloc():下一个大小无效:0x00000000009ce010 *** 分段错误(核心转储) @Karan,分段错误在 C 中很常见,并且在您分配的大小小于输入的大小时发生。在问题上下文中,您在堆上分配的内存较少,并尝试从您输入的大缓冲区数据中覆盖内存,因此您收到错误。有关更多信息,请参阅en.wikipedia.org/wiki/Segmentation_fault。【参考方案2】:

如果_getline() 读取了 10 个或更多字符,它将在未使用malloc() 分配的内存上调用realloc()。这是未定义的行为

此外,从realloc() 分配的内存将在对_getline() 的调用结束时泄漏。

此外,假设输入字符串是"0123456789\n"。然后,您将尝试将该值写入longest,但您将从不在此之前调用realloc(),这是必需的。

【讨论】:

【参考方案3】:

你的错误在这里:

int _getline(char s[])

这意味着_getline 是一个返回int 的函数,通过值获取指向char 的指针。

您实际上希望通过引用传递该指针(该指针必须指向使用malloc() 分配的内存或NULL)。

也就是说,你需要传递一个指向char的指针。

纠正该错误将迫使您也纠正所有后续错误。

仅在 NULL 上分别使用 free / realloc。在从malloccallocrealloc 返回的指针或指定返回此类指针的函数上。

【讨论】:

【参考方案4】:

当您的代码写入 malloc/realloc 为“管家信息”分配的内存时,您会收到 invalid old size 错误。这是他们存储“旧”分配大小的地方。当您传递给 realloc 的指针未正确初始化时也会发生这种情况,即它既不是 NULL 也不是以前从 malloc/calloc/realloc 返回的指针。

在您的情况下,传递给 realloc 的指针实际上是一个分配在自动内存中的数组 - 即它不是一个有效的指针。要解决此问题,请将linelongest 的声明更改如下:

char *line = malloc(MAXLINE), *longest = malloc(MAXLINE);

为避免内存泄漏,请确保在程序结束时调用 free(line)free(longest)

【讨论】:

【参考方案5】:

您正在尝试realloc() 未使用malloc() 动态分配的内存。你不能那样做。

另外,如果realloc() 失败,原始内存仍被分配,因此仍需要使用free() 释放。所以不要将realloc()的返回值赋给原始指针,除非它不为NULL,否则就是在泄漏原始内存。将realloc()的返回值先赋值给一个临时变量,检查它的值,只有realloc()成功后才赋值给原来的指针。

【讨论】:

以上是关于realloc() 无效的旧大小的主要内容,如果未能解决你的问题,请参考以下文章

realloc 使用详解(分析realloc invalid pointer指针无效等错误)

Realloc 无效指针。中止(核心转储)

新大小与旧大小相同时 realloc 的行为

动态分配内存-realloc

Realloc 没有调整指针数组的大小

realloc 和 memcpy 是如何工作的?