2017-04-17 55 views
2

当我运行以下程序时,我得到了一个损坏的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

然而,当我为了改变在test()功能noexcept规范true到触发拨打std::terminate(),我得到这个输出:

的libC++ abi.dylib:)X> 20

我认为的std ::终止(也许能够提供命名是因为它的未重整类型:有型 的std :: really_out_of_range的未捕获的异常终止明确地处理了每种标准异常类型,但显然不是这种情况,因为它也正确处理了我在上面定义的新异常类型。

所以,我的问题是为什么在std::terminate()中正确的typeinfo名称,但不是当我尝试直接访问它时?或者,更重要的是,std::terminate()调用哪个函数提供了一个未加密的类名?

+1

我怀疑'std :: terminate'只是对typeinfo名称进行了demangling。可能有一个它使用的环境内部函数。例如,G ++有'abi :: __ cxa_demangle'。 – cdhowie

+0

'typeid(anything).name()'的结果是实现定义的。 'std :: terminate()'不需要去掉(或者以任何特定的形式呈现一个异常的类型),并且没有标准的函数来去除名字。最后,像名字空间'std'一样添加声明给出了未定义的行为。 – Peter

回答

0

cdhowie“的评论后,我在这里找到了答案:Unmangling the result of std::type_info::name

基本上,你#include <cxxabi.h>,如果你使用GNU叫abi::__cxa_demangle。但是你必须小心内存管理。

但是,您也可以使用boost。然后您只需#include <boost/core/demangle.hpp>并致电boost::core::demangle(name)

相关问题