当前位置: 首页 > 知识库问答 >
问题:

为什么在这个C程序中存在内存泄漏,以及在给定的限制条件下如何解决它?

贲宏硕
2023-03-14

这是我在真实代码中遇到的问题的最小工作示例。

#include <iostream>

namespace Test1 {
    static const std::string MSG1="Something really big message";
}

struct Person{
    std::string name;
};

int main() {
    auto p = (Person*)malloc(sizeof(Person));
    p = new(p)Person();
    p->name=Test1::MSG1;

    std::cout << "name: "<< p->name << std::endl;
    
    free(p);
    
    std::cout << "done" << std::endl;

    return 0;
}

当我编译它并通过valgrind运行它时,它给我这个错误:< code >绝对丢失:1个块中有31个字节

    < li >在上面的示例中,我必须使用< code>malloc,因为在我的真实代码中,我在我的C项目中使用C库,它在内部使用这个< code>malloc。所以我无法摆脱< code>malloc用法,因为我没有在代码中的任何地方显式地使用它。 < li >我需要在代码中反复重新分配< code>Person的< code>std::string name。

共有3个答案

谷梁英毅
2023-03-14

正如在其他回答中提到的,泄漏的来源是没有调用< code>Person的< code>name成员的析构函数。当调用< code>Person的析构函数时,通常会隐式调用它。但是,< code>Person永远不会被析构。< code>Person实例的内存只是通过< code>free来释放。

因此,正如您必须在malloc之后显式调用带有位置new的构造函数一样,您也需要在释放之前显式调用析构函数。

您还可以考虑重载新建删除运算符。

struct Person {
    std::string name;
    void * operator new (std::size_t) { return std::malloc(sizeof(Person)); }
    void operator delete (void *p) { std::free(p); }
};

这样,您可以正常使用newdelete,而在下面它们将使用mallocfree

int main (void) {
    auto p = new Person;
    //... 
    delete p;
}

这样,您可以更自然地使用智能指针。

int main (void) {
    auto p = std:make_unique<Person>();
    //... unique pointer will delete automatically
}

当然,您可以将unique_ptr与自定义删除器一起使用,并显式调用mallocfree,但这会更加麻烦,并且您的删除器仍然需要知道显式调用析构函数。

刘兴修
2023-03-14

您必须在 free(p) 之前手动调用析构函数;:

p->~Person();

或者< code>std::destroy_at(p),这是一回事。

林修真
2023-03-14

代码的重要部分一行一行。。。

为一个人对象分配内存:

auto p = (Person*)malloc(sizeof(Person));

通过调用其构造函数在已分配的内存中构造一个 Person 对象:

p = new(p)Person();

释放通过 malloc 分配的内存:

free(p);

通过放置new调用构造函数将创建一个std::string。该字符串将在析构函数中被销毁,但从未调用析构函数free不调用析构函数(就像malloc不会调用构造函数一样)。

< code>malloc只分配内存。Placement new只在已经分配的内存中构造对象。因此,您需要在调用< code>free之前调用析构函数。这是我所知道的唯一一种正确且有必要显式调用析构函数的情况:

auto p = (Person*)malloc(sizeof(Person));
p = new(p)Person();
p->~Person();
free(p);
 类似资料:
  • 在阅读了大量有关MAT的内容后,我使用我的生产堆转储来分析内存泄漏问题。下面是泄漏报告错误: 线程org.apache.tomcat.util.threads.taskthread@0x6d8be0a30 http-bio-8443-exec-115保留总大小为3,695,816,440(89.03%)字节的局部变量。 内存累积在“'<'System class Loader'>”加载的“java

  • 问题内容: 由于GWT是用javascript编译且代码是用JAVA编写的事实,解决GWT内存泄漏的最佳方法是什么? 问题答案: 我可以推荐2件事: 阅读这篇文章 处理完所有引用后,将其无效。 祝好运!

  • 问题内容: 我有一个Python程序,它运行一系列实验,没有打算从一个测试存储到另一个测试的数据。我的代码包含一个我完全找不到的内存泄漏(我已经查看了内存泄漏的其他线程)。由于时间限制,我不得不放弃寻找泄漏的机会,但是如果我能够隔离每个实验,该程序可能会运行足够长的时间以产生所需的结果。 在单独的线程中运行每个测试是否有帮助? 还有其他隔离泄漏影响的方法吗? 具体情况详 我的代码分为两部分:实验运

  • 本文向大家介绍IOS 常见内存泄漏以及解决方案,包括了IOS 常见内存泄漏以及解决方案的使用技巧和注意事项,需要的朋友参考一下 IOS 常见内存泄漏以及解决方案 整理了几个内存泄漏的例子,由于转载地址已经找不到了,在这里就不一一列出来了。 1 OC和CF转化出现的内存警告 2,循环参照 A有个属性参照B,B有个属性参照A,如果都是strong参照的话,两个对象都无法释放。 这种问题常发生于把del

  • 问题内容: 您经常在网络上读到使用闭包是JavaScript中大量内存泄漏的原因。在大多数情况下,这些文章都涉及混合脚本代码和DOM事件,其中脚本指向DOM,反之亦然。 我了解关闭可能是一个问题。 但是Node.js呢?在这里,我们自然没有DOM-因此像浏览器一样,没有机会出现内存泄漏的副作用。 关闭可能还会有什么其他问题?有人可以详细说明或指向我关于此的很好的教程吗? 请注意,此问题明确针对No

  • 问题内容: 我有大约五种这样的方法,但是由于seriesColors是静态的,所以想知道上面的代码是否会导致内存泄漏。 如果存在内存泄漏,那么该如何解决? 在这两个代码中,哪一个存在严重缺陷? 问题答案: 静态变量在类的所有实例之间共享。(使用“ new”运算符创建一个实例。) 在这些示例中;使用静态(实例变量)存储颜色可能不是一个好主意,因为实例之间会相互干扰。该变量应更改为“普通”实例变量。

  • 本文向大家介绍什么是内存泄漏?相关面试题,主要包含被问及什么是内存泄漏?时的应答技巧和注意事项,需要的朋友参考一下 答:一般我们所说的内存泄漏指的是堆内存的泄漏。堆内存是程序从堆中为其分配的,大小任意的,使用完后要显示释放内存。当应用程序用关键字new等创建对象时,就从堆中为它分配一块内存,使用完后程序调用free或者delete释放该内存,否则就说该内存就不能被使用,我们就说该内存被泄漏了。

  • 严重:web应用程序创建了一个ThreadLocal,其键类型为[org.apache.log4j.helpers.ThreadLocalMap](值为[org.apache.log4j.helpers.ThreadLocalMap@3ac5b23e])和值类型为[java.util.Hashtable](值为[{userhost=192.168.15.90,userid=127,username