Метод копирования CRTP предупреждает о возможной утечке памяти

У меня есть иерархия объектов, и мне нужно иметь возможность клонировать объекты из базового класса. Я следовал типичному шаблону CRTP, за исключением того, что я также хочу иметь возможность возвращать дочерний класс, если copy вызывается непосредственно для дочернего класса. Чтобы сделать это, я последовал предложению здесь: https://stackoverflow.com/a/30252692/1180785

Кажется, он работает нормально, но Clang предупреждает меня о возможной утечке памяти. Я сократил код до этого MCVE:

template <typename T>
class CRTP {
protected:
virtual CRTP<T> *internal_copy(void) const {
return new T(static_cast<const T&>(*this));
}

public:
T *copy(void) const {
return static_cast<T*>(internal_copy());
}

virtual ~CRTP(void) = default;
};

class Impl : public CRTP<Impl> {
};

int main(void) {
Impl a;
Impl *b = a.copy();
delete b;
}

Насколько я могу сказать, там нет никакой возможной утечки памяти, но запуск Clang через XCode показывает это:

Clang потенциальная утечка памяти

Является здесь утечка памяти? Если нет, что является причиной ложного срабатывания и как я могу обойти это? (Я бы предпочел не отключать статический анализ)

6

Решение

Я нашел обходной путь, который делает анализатор счастливым, в то же время позволяя использовать этот шаблон. Просто обратная связь между copy а также internal_copy:

template <typename T>
class CRTP : public Base {
protected:
virtual CRTP<T> *internal_copy(void) const {
return copy();
}

public:
T *copy(void) const {
return new T(static_cast<const T&>(*this));
}
};

Это все еще работает в контексте первоначального предложения Вот, потому что при решении copy внутри CRTP он предпочтет переопределение CRTP (даже если это не виртуальный метод), поэтому бесконечного цикла нет.

Что касается того, почему анализатор доволен этим заказом, но недоволен исходным заказом, я понятия не имею.

1

Другие решения

Я думаю, что анализатор запутывается static_cast в вашем copy метод. Если вы просто измените его на dynamic_cast, он перестает помечать строку как утечку памяти. Это заставляет меня поверить, что он думает, что вы, возможно, используете тип базового типа (CRTP<T>) к его производному типу (T), который, конечно, будет недействительным при разыменовании. Вы, очевидно, этого не делаете, так что это может быть ошибкой в ​​детекторе утечки, или это может быть связано с чем-то более тонким, чем то, о чем я сейчас думаю. Это не может быть ошибкой сейчас, но если Impl становится более сложным типом (например, с множественным наследованием), он может стать проблемой (как и ваш static_cast в вызове копирования-CTOR).

Эта реализация (с меньшим количеством приведений) также имела нулевые утечки:

template <typename T>
class CRTP {
protected:
virtual T *internal_copy() const {
return new T(static_cast<const T&>(*this));
}

public:
T *copy() const {
return internal_copy();
}

virtual ~CRTP() = default;
};
1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector