【问题标题】:Memory Leak caused by Initializer List?初始化列表引起的内存泄漏?
【发布时间】:2020-05-10 05:42:53
【问题描述】:

我的代码中有内存泄漏,根据 valgrind,所有这些都来自我班级的构造函数;这里是它的代码:

  School::School(unsigned int NumberOfClasses[]) :
        first(*new Grade<Student, std::equal_to<Student>>(NumberOfClasses[0])),
        second(*new Grade<Student, std::equal_to<Student>>(NumberOfClasses[1])),
        third(*new Grade<Student, std::equal_to<Student>>(NumberOfClasses[2])) {

}

Grade 是我创建的一个特殊数组模板,它获取元素(在本例中为 Student)和元素的比较函数(我也提供了);它有一个构造函数和一个析构函数,可以在没有内存泄漏的情况下工作。这是构造函数的签名:

Grade<Element, Compare> :: Grade(unsigned int size);

由于我的学校是 3 年级,它的析构函数是 =default;

这是我从 valgrind 得到的:

    8 bytes in 1 blocks are indirectly lost in loss record 1 of 6
==21426==    at 0x4C2A888: operator new[](unsigned long) (vg_replace_malloc.c:423)
==21426==    by 0x4041B8: Grade<BmbSchool::Student, std::equal_to<BmbSchool::Student> >::Grade(unsigned int) (GradeImp.h:9)
==21426==    by 0x40298B: BmbSchool::School::Grade(unsigned int*) (School.cpp:27)
==21426==    by 0x405B6C: main (BmbSchool.cpp:148)

我得到的另一种错误,非常相似,是:

==21426== 32 (24 direct, 8 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 6
==21426==    at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==21426==    by 0x402974: BmbSchool::School::Grade(unsigned int*) (School.cpp:28)
==21426==    by 0x405B6C: main (BmbSchool.cpp:148)

有什么意义吗?我该如何解决这个问题?我可以假设在定义数组时不会抛出任何 bad_alloc 异常。

编辑:对学校的定义是 -

    Grade<Student, std::equal_to<Student>> first;
    Grade<Student, std::equal_to<Student>> second;
    Grade<Student, std::equal_to<Student>> third;

【问题讨论】:

  • 你能提供你的School类的定义吗?
  • 几乎从不做*new ...。只需删除*new,生活就会变得更好。
  • *new 之后很难不泄漏。它使new 返回的指针不可访问。根据您对* 的结果所做的操作,您可能 能够将其取回。但这几乎总是一个错误。您可能会受到 Java 或 C# 等其他语言的影响,其中需要 new 来实例化任何内容。在 C++ 中,情况并非如此。它支持值语义,即使需要动态分配 new 也不鼓励使用 std::make_uniquestd::make_shared
  • 除上述之外......如果first等是参考成员,他们可能不应该是。而且由于没有minimal reproducible example...

标签: c++ oop memory-leaks valgrind initializer


【解决方案1】:

如果你可以使用 C++11 或更高版本,你可以使用 std::array,比如

 School::School(const std::array<unsigned int, 3>& NumberOfClasses) :
 // as Remy Lebeau's answer

我希望编译器产生相似的机器代码,但你将获得一些编译时检查。

【讨论】:

    【解决方案2】:

    泄漏在于您滥用new。您正在动态分配 3 个 Grade 对象,但随后取消引用指针以将这些对象传递给您的 3 个数据成员的复制构造函数。你从来没有deletenew'ed的对象,因此泄漏。

    在这种情况下,您根本不需要使用 new。只需将您的输入值直接传递给您使用 new 调用的数据成员本身的同一构造函数:

    School::School(unsigned int NumberOfClasses[]) :
        first(NumberOfClasses[0]),
        second(NumberOfClasses[1]),
        third(NumberOfClasses[2])
    {
    }
    

    【讨论】:

      猜你喜欢
      • 2013-08-12
      • 2019-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-08
      • 2021-06-15
      • 1970-01-01
      相关资源
      最近更新 更多