【问题标题】:C++ casted realloc causing memory leakC ++强制重新分配导致内存泄漏
【发布时间】:2011-02-18 22:50:09
【问题描述】:

我正在使用我找到的here 函数通过 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 编译)声明)坚持,但我认为这是泄漏的根源。谁能解释一下?

谢谢

【问题讨论】:

  • page->pageData[page->size] = 0 需要什么?无论如何都会存储大小。

标签: c++ casting realloc


【解决方案1】:

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

【讨论】:

  • 我不认为 OP 的问题是检测内存泄漏;它正在寻找内存泄漏的原因。如果我们已经将问题缩小到这个函数,Valgrind 就不适合这个了。最后,Valgrind 只是 *nix,这可能是个问题。不要投反对票——只是指出潜在的问题。
  • @Billy ONeal:干杯,编辑帖子以改进您指出的一些问题。
【解决方案2】:

您发布的代码(据我所知)是正确的。如果漏水,我 怀疑您在某些时候忘记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;
}

【讨论】:

  • 谢谢,向量解决了这个问题。我没有使用它们,因为我实际上是在构建这个程序作为学习 C++ 的一种方式,所以目前我对它很不擅长。作为参考,我应该在每次调用 storePage 之前调用 free() 吗?我在每次调用时都使用相同的 WebpageData 实例。干杯。
  • 另外,将矢量 转换为字符串的最佳方法是什么?我认为我陪审团操纵的迭代过程非常糟糕。
  • @wyatt:不——不是每次通话都免费,但在你完成内存块的最后。将 vector 转换为字符串的最佳方法是 &amp;myVector[0].
【解决方案3】:

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

其他想法:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 2012-08-10
    • 2021-09-21
    • 2021-05-01
    • 2020-04-06
    • 1970-01-01
    • 2018-04-21
    相关资源
    最近更新 更多