1

我正在使用我在这里找到的一个函数通过 cURL 将网页保存到内存中:

struct WebpageData {
    char *pageData;
    size_t size;
};

size_t storePage(void *input, size_t size, size_t nmemb, void *output) {
    size_t realsize = size * nmemb;

    struct WebpageData *page = (struct WebpageData *)output;

    page->pageData = (char *)realloc(page->pageData, page->size + realsize + 1);
    if(page->pageData) {
        memcpy(&(page->pageData[page->size]), input, realsize);
        page->size += realsize;
        page->pageData[page->size] = 0;
    }

    return realsize;
}

并找到该行:

page->pageData = (char *)realloc(page->pageData, page->size + realsize + 1);

导致每次调用几百字节的内存泄漏。我对原始来源所做的唯一真正改变是将有问题的行转换为(char *),我的编译器(gcc,g++,特别是如果它是 ac/c++ 问题,但 gcc 也不会用 uncast 编译)声明)坚持,但我认为这是泄漏的根源。谁能解释一下?

谢谢

4

3 回答 3

1

您发布的代码(据我所知)是正确的。如果它泄漏,我怀疑你free()在某个时候忘记了内存块。 realloc如果它不能简单地扩展现有的内存块,则允许创建一个全新的内存块,这对您很感兴趣。当然也允许分配比需要更大的块,这可能导致幻像泄漏。

现在,既然您使用的是 C++,我不得不问:您为什么不使用它 std::vector呢?

struct WebpageData {
    std::vector<char> pageData;
    size_t size;
};

size_t storePage(void *input, size_t size, size_t nmemb, void *output) {
    size_t realsize = size * nmemb;
    WebpageData *page = reinterpret_cast<WebpageData *>(output);

    page->pageData.resize(page->size + realsize + 1);
    memcpy(&(page->pageData[page->size]), input, realsize);
    page->size += realsize;
    page->pageData[page->size] = 0;

    return realsize;
}
于 2010-05-13T05:10:03.933 回答
0

如果在 *nix 上开发,一般来说,我会尝试使用 valgrind ( http://valgrind.org/ ) 运行程序以解决内存泄漏问题(在这种情况下,我认为你确实知道内存分配在哪里,但它在哪里被释放?)。在这种情况下,我建议不要在 c++ 程序中使用 malloc、realloc 和其他类似的 c 内存管理,除非绝对必要和不可避免。应该避免使用 c++ 内存管理工具,在这种情况下,我认为内存没有被正确释放。使用 c++ Vectors 可能会让您的生活更轻松,因为您无需担心数组的大小调整和跟踪内存分配的所有变化。

于 2010-05-13T05:08:24.577 回答
0

演员表不应该对 realloc 产生任何影响。你确定你有内存泄漏?代码是附加数据的,所以如果你要求它存储页面 3 次,每次 1kB 的数据,它将存储 3kB。这是您复制和粘贴代码时的意图吗?当然,当你完成它时,你必须在某个地方释放()块。

其他想法:

  • 您重新分配的内存最初是 malloc'd 还是 realloc'd?

  • 请注意,如果您无法重新分配数据,您将丢失所有数据。如果你重新分配到一个临时指针,然后只覆盖 page->pageData 如果它是有效的,这不会发生,你将能够向调用者报告失败(尽管这在实践中不太可能发生,如果确实如此,您可能会遇到更大的问题!)

  • 每次收到新数据时,您都会重新分配块。分配比所需更大的块可能会更有效,将数据检索到其中,然后仅在收到所有数据后将其重新分配到精确匹配的块中,这样您就可以避免重复重新分配块。

于 2010-05-13T05:19:20.260 回答