gpt4 book ai didi

c++ - 带有标签调度的 const 成员构造函数中的内存泄漏

转载 作者:搜寻专家 更新时间:2023-10-31 02:04:17 25 4
gpt4 key购买 nike

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

Bar 的构造函数的初始化列表中,我调用函数 make_Foo,它返回正确的 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;
}

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

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

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

最佳答案

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

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

关于c++ - 带有标签调度的 const 成员构造函数中的内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53762186/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com