【问题标题】:"invalid next size" exception while reallocing memory重新分配内存时出现“无效的下一个大小”异常
【发布时间】:2016-03-06 14:27:53
【问题描述】:

P.S.:我几乎有所有关于“无效的下一个尺寸”的问题,但它们对我没有帮助,因为我没有另一段 malloc 或 realloc 代码,所以排除了。另外,我没有分配超出内存空间的限制,所以我在这方面也很好。

我有下面的代码给我 - *** Error in./server_issue': realloc(): invalid next size: 0x08249170 ***`.

我无法确定问题所在,我一次只分配 64 个字节,因此我没有超出内存地址空间,并且还有其他内存分配可能损坏了我的堆内存。

错误说,下一个大小无效,但正如我的最后一个日志告诉 Reallocating 64 bytes, Aborted (core dumped) 所以这意味着我仍在尝试分配 64 个字节。那么,为什么会出错呢?

对于 HTML 文件,有任何超过 256 字节的文件。

代码:(重现问题的最少代码)

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

typedef char BYTE;
bool load(FILE*, BYTE**, size_t*);

int main(void)
{
    FILE* file = fopen("/home/university/psets/pset6/pset6_working/public/hello.html", "r");
    BYTE* content;
    size_t length;
    load(file, &content, &length);
}

bool load(FILE* file, BYTE** content, size_t* length)
{
    int totalLength = 0;
    int readBytes = 0;
    *content = NULL;

    BYTE* fileContentTemp[64]; // working with 222222
    while ((readBytes = fread(fileContentTemp, 1, 64, file)) > 0)
    {
        printf("Reallocating %d bytes, ", readBytes);
        *content = realloc(*content, readBytes);
        printf("%p\n", *content);
        if(totalLength != 0)
        {
            memcpy(*content + totalLength + 1, fileContentTemp, readBytes);        
        } else{
            memcpy(*content + totalLength, fileContentTemp, readBytes);        
        }
        totalLength = totalLength + readBytes;
    }

    *length = totalLength;

    printf("CC image: %s\n", *content);
    printf("length is %d\n", *length);
    printf("fileContent %p\n", *content);

    return true;
}

输出:

Reallocating 64 bytes, 0x8249170
Reallocating 64 bytes, 0x8249170
*** Error in `./server_issue': realloc(): invalid next size: 0x08249170 ***
Reallocating 64 bytes, Aborted (core dumped)


更新: 即使我分配 64 个字节而不是使用 readBytesrealloc ,我也会得到同样的错误。由于这条线,我收到错误 - *content = realloc(*content, readBytes);

【问题讨论】:

    标签: c memory memory-management realloc


    【解决方案1】:

    另外,我没有分配超出内存空间的限制,所以我在这方面也很好。

    过分确定您的代码是使调试更加困难的好方法。怀疑一切都是错的。


    您没有分配足够的内存,因为您错误地使用了realloc

    p = realloc(p, n) 不会添加 n 字节到分配中,它会将总分配大小更改为您告诉它的大小。

    每次通过循环时,您都会传递readBytes,这是您要复制的额外 个字节数。所以你的缓冲区永远不会增长。但是你继续写到它的结尾:

    memcpy(*content + totalLength, ...
    

    totalLength 在整个循环中不断增长。


    在这样的循环中调用realloc 在性能方面通常是个坏主意。您应该预先分配足够的总空间,然后在循环中读取它。

    要获得总文件大小:

    size_t get_file_size(FILE *f)
    {
        long oldpos;
        size_t result;
    
        // Save the original file position
        oldpos = ftell(f);
    
        // Seek to the first byte past the end of the file
        fseek(f, 0, SEEK_END);
    
        // Get the file position - the number of bytes in the file
        result = ftell(f);
    
        // Return the file position to where it was
        fseek(f, oldpos, SEEK_SET);
    
        return result;
    }
    

    这是一个测试,以证明我所说的关于 realloc 的内容。请注意,这通常使用malloc_usable_size,这是不好的做法。

    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    
    int main(void)
    {
        int i;
        char *p = NULL;
    
        for (i = 0; i < 10; i++) {
            p = realloc(p, 16);
            printf("[%d] size: %zd\n", i, malloc_usable_size(p));
        }
    
        return 0;
    }
    

    输出:

    $ gcc -Wall -Werror -o realloc realloc.c 
    $ ./realloc 
    [0] size: 24
    [1] size: 24
    [2] size: 24
    [3] size: 24
    [4] size: 24
    [5] size: 24
    [6] size: 24
    [7] size: 24
    [8] size: 24
    [9] size: 24
    

    请注意,malloc_usable_size() 返回相同的值,即使在多次调用 realloc 并传递相同的大小之后也是如此。此外,即使我们分配了 16 个字节,它也会返回 24,这是分配器实现细节的结果。

    来自malloc_usable_size 的手册页:

    注意事项

    由于对齐和最小大小限制,malloc_usable_size() 返回的值可能大于请求的分配大小。尽管应用程序可以覆盖多余的字节而不会产生不良影响,但这不是好的编程习惯:分配中多余的字节数取决于底层实现。

    这个函数的主要用途是调试和自省。

    【讨论】:

    • 即使我分配 64 个字节而不是使用 readBytes,我也会得到同样的错误。由于这条线,我收到错误 - *content = realloc(*content, readBytes);
    • "realloc with expand/shrink the existing pointer by specified size" 同样,您对realloc 的理解是不正确的。它将分配大小更改为给定的值。它不会添加到它。如果你调用p = realloc(p, 10) 七次,那么仍然只分配了 10 个字节。不是 70。在您的代码中,这将涉及将 totalLength + readSize 传递给 realloc。你必须告诉它你想要的字节总数。
    • 仔细阅读。 改变大小... size字节。
    • 这是一个很好的收获,请点赞!我很少投票,所以我在“神奇”下添加了书签:(
    • 您可能在某处仍有内存问题。我会调查valgrind;它是用于检测此类内存问题的工具。如果您使用调试信息 (gcc -g) 编译代码,它会非常有效。
    猜你喜欢
    • 2013-09-16
    • 2021-10-20
    • 2014-01-23
    • 2014-05-18
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多