Неверное имя typeinfo для исключений

Когда я запускаю следующую программу, я получаю искаженное имя typeinfo.

#include <iostream>
#include <stdexcept>
#include <typeinfo>

namespace std
{

class really_out_of_range
    : public out_of_range
{
public:
    explicit really_out_of_range(const string& __s) : out_of_range(__s) {}
    explicit really_out_of_range(const char* __s)   : out_of_range(__s) {}

    virtual ~really_out_of_range() _NOEXCEPT {}
};

}

void test () noexcept(false)
{
    throw std::really_out_of_range("x > 20");
}

int main () noexcept(true)
{
    try {
        test();
    } catch (const std::exception& e) {
        std::cout << "Exception caught: " << typeid(e).name() << ": " << e.what() << '\n';
    } catch (...) {
        std::cout << "Unknown exception caught\n";
    }
}

Вот результат:

Обнаружено исключение: St19really_out_of_range: x> 20

Однако, когда я меняю спецификацию noexcept в функции test() на true, чтобы вызвать вызов std::terminate(), я получаю следующий результат:

libc ++ abi.dylib: завершение с неперехваченным исключением типа std :: really_out_of_range: x> 20

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

Итак, мой вопрос: почему имя typeinfo правильное в std::terminate(), а не тогда, когда я пытаюсь получить к нему доступ напрямую? Или, что более важно, какую функцию вызывает std::terminate(), которая предоставляет несвязанное имя класса?


person IntellectualKitty    schedule 17.04.2017    source источник
comment
Я подозреваю, что std::terminate просто разоблачает имя typeinfo. Вероятно, он использует внутреннюю функцию среды. Например, в G ++ есть abi::__cxa_demangle.   -  person cdhowie    schedule 17.04.2017
comment
Результат typeid(anything).name() определяется реализацией. std::terminate() не требуется для распознавания (или представления типа исключения в какой-либо конкретной форме), и нет стандартной функции для распознавания имени. Наконец, добавление объявлений в пространство имен std, как у вас, дает неопределенное поведение.   -  person Peter    schedule 17.04.2017


Ответы (1)


После комментария cdhowie я нашел здесь ответ: Распознавание результата std :: type_info :: name

По сути, вы #include <cxxabi.h> и вызываете abi::__cxa_demangle, если используете GNU. Но нужно быть осторожным с управлением памятью.

Однако вы также можете использовать ускорение. Тогда вы просто #include <boost/core/demangle.hpp> и звоните boost::core::demangle( name ).

.

person IntellectualKitty    schedule 17.04.2017