Утечка памяти в конструкторе-члене const с диспетчеризацией тегов - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть класс Bar, в котором есть член типа Foo.Класс Foo должен создаваться только в определенных фиксированных и постоянных состояниях, которые различаются на основе Tag.Поскольку я не хочу, чтобы Foo создавался в каком-либо другом состоянии, я сделал его конструктор закрытым и реализовал фабрику FooFactory.

. В списке инициализатора конструктора Bar я вызываюфункция make_Foo, которая возвращает правильный экземпляр Foo на основе Tag.

#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;
}

Я хочу, чтобы генерировалось исключение, когда Foo создается с Tag::C, чтоне реализованы.Приведенный выше код вызывает это исключение, но Вальгринд Мемчек говорит, что в этом случае происходит утечка памяти.

При дальнейшем исследовании я вижу, что, хотя bar.foo не создается на заводе при пропуске Tag::C, bar.foo все еще инициализируется с неизвестным Tag и пустым std::string.Это память, которая просочилась в этом случае?Как я могу избежать этого при возникновении исключения?

пс.В действительности Foo является нетиповым классом шаблона, а для Tag::C используется другой параметр шаблона.Вот почему мне нужна диспетчеризация тегов.

1 Ответ

0 голосов
/ 13 декабря 2018

Может быть «утечка памяти», потому что программа преждевременно завершает работу.Чтобы выполнить все деструкторы и освободить память, вы не должны позволять исключению выходить из функции main (или иным образом вызывать std::abort или иным образом вызывать повышение сигнала терминала).

Объекты со статическимдлительность уничтожается после основных возвратов, и эта очистка статических объектов не происходит, если процесс завершается.Такие статические объекты могут иметь выделенную динамическую память, которая может вытекать, если статические объекты не уничтожены.Даже если вы этого не сделаете, стандартная библиотека может использовать объекты со статическим хранилищем.Например, объект std::cout.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...