исключение — статический анализ без исключений «нарушения» в переполнении стека

Я пытаюсь написать безопасный код исключения. Я считаю, что использование спецификатора noexcept в C ++ 11 делает эту цель намного более достижимой.

Общая идея, конечно же, заключается в том, что функция должна быть помечена как noexcept, если и только если все вызываемые ею функции также помечены как noexcept.

Проблема заключается в том, что в большой кодовой базе, где исправления от разных людей часто объединяются, трудно обеспечить сохранение этой согласованности.

Поэтому я хотел бы иметь возможность запустить статический анализ, в котором можно было бы перечислить все места, где функция, помеченная как nothrow, вызывает функцию, которая не помечена как nothrow.

Насколько я вижу на странице руководства, GCC не может помочь мне здесь. Существуют ли какие-либо автономные инструменты, которые могут мне помочь? Или, может быть, некоторые другие компиляторы?

15

Решение

Это, конечно, кажется возможным, если вы избегаете указателя на функции (и считаете их небезопасными), используя ABT программы. AST от Clang (несмотря на название) такой ABT: вы увидите как объявления, так и определения функций. Выполняя свою работу по одному определению за раз, у вас уже будет хороший базовый уровень.

С другой стороны, мне интересно, практическое. Видите, проблема в том, что любая функция, выполняющая выделение памяти, (добровольно) помечается как потенциально выбрасываемая (потому что new никогда не возвращает ноль, но бросает bad_alloc вместо). Поэтому ваш noexcept будет ограничено несколькими функциями в большинстве случаев.

И, конечно, есть все динамические условия, такие как @GManNickG, например:

void foo(boost::optional<T> const t&) {
if (not t) { return; }

t->bar();
}

Даже если T::bar является noexceptразыменование optional<T> может скинуть (если ничего нет). Конечно, это игнорирует тот факт, что мы уже исключили это (здесь).

Не имея ясно условия когда функция может throw, static анализ может оказаться … бесполезным. Языковые идиомы разработаны с учетом исключений.


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

template <typename T>
class maybe {
public:

template <typename OnNone, typename OnJust>
void act(OnNone&& n, OnJust&& j) noexcept(noexcept(n()) and
noexcept(j(std::declval<T&>())))
{
if (not _assigned) { n(); return; }
j(*reinterpret_cast<T*>(&_storage));
}

private:
std::aligned_storage<sizeof(T), alignof(T)>::type _storage;
bool _assigned;
};

// No idea if this way of expressing the noexcept dependency is actually correct.
6

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

Других решений пока нет …

По вопросам рекламы [email protected]