c++ - 使用标记分派(dispatch)的 const 成员构造函数中的内存泄漏

标签 c++ memory-leaks constructor c++14

我有一个类 Bar,它有一个 Foo 类型的成员。类 Foo 应该仅在某些固定和恒定状态下构造,这些状态是基于 Tag 进行区分的。由于我不希望在任何其他状态下构造 Foo,因此我将其构造函数设为私有(private)并实现了一个工厂 FooFactory

Bar 构造函数的初始值设定项列表中,我调用函数 make_Foo,该函数根据标签

#include <stdexcept>
#include <string>
#include <iostream>

enum class Tag
{
    A,
    B,
    C
};

class Foo
{
public:
    friend class FooFactory;
    const Tag tag;
    const std::string string;
private:
    Foo(Tag tag, std::string string): 
    tag {tag}, string {string}
    {};
};

class FooFactory
{
public:
    static Foo A()
    {
        return Foo(Tag::A, {"This is string A"});
    }

    static Foo B()
    {
        return Foo(Tag::B, {"This is string A"});
    }
};

Foo make_Foo(Tag tag)
{
    switch(tag)
    {
        case Tag::A: return FooFactory::A();
        case Tag::B: return FooFactory::B();
        default: throw std::runtime_error("Called with invalid Tag.");
    }
}

class Bar
{
public:
    std::string another_string;
    const Foo foo;

    Bar(Tag tag, std::string another_string): 
    another_string {another_string}, foo {make_Foo(tag)}
    {};
};

int main()
{
    Tag tag = Tag::C;
    Bar bar(tag, "This is a string");
    std::cout << "bar constructed" << std::endl;
}

我希望在使用 Tag::C 构造 Foo 时抛出异常,但未实现。上面的代码抛出了这个异常,但是Valgrind Memcheck说这种情况下存在内存泄漏。

经过进一步调查,我发现即使在传递 Tag::Cbar.foo 不是由工厂创建的,bar.foo 仍然使用未知的 Tag 和空的 std::string 进行初始化。这是本例中泄漏的内存吗?抛出异常时如何避免这种情况发生?

ps。实际上,Foo 是一个非类型模板类,对于Tag::C,使用了另一个模板参数。这就是为什么我需要标签调度。

最佳答案

由于程序提前终止,可能会出现“内存泄漏”。为了执行所有析构函数并释放内存,您不得允许异常转义 main 函数(或调用 std::abort 或以其他方式导致终端信号被提高)。

具有静态持续时间的对象将在 main 返回后被销毁,并且如果进程终止,则不会发生静态对象的清理。此类静态对象可能分配了动态内存,如果静态对象未被销毁,则动态内存可能会泄漏。即使您不这样做,标准库也可能使用具有静态存储的对象。例如,std::cout 对象。

关于c++ - 使用标记分派(dispatch)的 const 成员构造函数中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53762186/

相关文章:

C++ 这个函数会泄漏吗?

java - 通过复制构造函数在 Java 中复制对象而不影响原始对象

c++ - 从集合中生成大小为 k 的所有子集

c++ - 从另一个程序 Linux 或 cygwin 运行外部程序

c++ - 检测 windows jpeg 图标

c++ - 为 vector 的 vector 分配内存

c - 如何发现代码中的内存泄漏问题

c++ - 当我声明一个我不使用的 vector 时泄漏 16 字节的内存

python - python中类构造函数的职责是什么?

java - 如果子类构造函数调用的参数结构与其父类(super class)构造函数不匹配,会发生什么