이 질문 / 답변에 대한 관심과 GManNickG 의 귀중한 피드백을 감안할 때 코드를 약간 정리했습니다. 두 가지 버전이 제공됩니다. 하나는 C ++ 11 기능이 있고 다른 하나는 C ++ 98 기능 만 있습니다.
파일 type.hpp
#ifndef TYPE_HPP
#define TYPE_HPP
#include <string>
#include <typeinfo>
std::string demangle(const char* name);
template <class T>
std::string type(const T& t) {
return demangle(typeid(t).name());
}
#endif
파일 type.cpp (C ++ 11 필요)
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
// enable c++11 by passing the flag -std=c++11 to g++
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
용법:
#include <iostream>
#include "type.hpp"
struct Base { virtual ~Base() {} };
struct Derived : public Base { };
int main() {
Base* ptr_base = new Derived(); // Please use smart pointers in YOUR code!
std::cout << "Type of ptr_base: " << type(ptr_base) << std::endl;
std::cout << "Type of pointee: " << type(*ptr_base) << std::endl;
delete ptr_base;
}
다음을 인쇄합니다.
ptr_base Base*
유형 : pointee 유형 :Derived
Linux 64 비트에서 g ++ 4.7.2, g ++ 4.9.0 20140302 (시험용), clang ++ 3.4 (트렁크 184647), clang 3.5 (트렁크 202594) 및 g ++ 4.7.2 (Mingw32, Win32 XP SP2)로 테스트되었습니다.
C ++ 11 기능을 사용할 수없는 경우 C ++ 98에서 수행 할 수있는 방법 은 다음과 같습니다. 파일 type.cpp 는 다음과 같습니다.
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
struct handle {
char* p;
handle(char* ptr) : p(ptr) { }
~handle() { std::free(p); }
};
std::string demangle(const char* name) {
int status = -4; // some arbitrary value to eliminate the compiler warning
handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );
return (status==0) ? result.p : name ;
}
#else
// does nothing if not g++
std::string demangle(const char* name) {
return name;
}
#endif
(2013 년 9 월 8 일 업데이트)
허용 된 답변 (2013 년 9 월 7 일 현재) ,에 대한 호출 abi::__cxa_demangle()
이 성공 하면 로컬 스택 할당 배열에 대한 포인터를 반환합니다 . 아야!
또한 버퍼를 제공 abi::__cxa_demangle()
하면 힙에 할당 된 것으로 간주합니다. 스택에 버퍼를 할당하는 것은 버그입니다 (gnu 문서에서) : " output_buffer
길이가 충분하지 않으면를 사용하여 확장됩니다 realloc
." 스택에 대한 포인터를 호출 realloc()
하는 중 ... 아야! ( Igor Skochinsky 의 친절한 의견 도 참조하십시오 .)
단지 예 16, 작은 일 1024에서 SEP ((7), 2013) 허용 대답에 버퍼 크기를 줄이고, 이름으로 뭔가를 줄 : 당신은 쉽게 이러한 버그를 모두 확인할 수 없습니다 때문에 (이상 15 일 realloc()
입니다 호출 되지 않음 ). 그래도 시스템과 컴파일러 최적화에 따라 출력은 쓰레기 / 없음 / 프로그램 충돌입니다.
두 번째 버그를 확인하려면 버퍼 크기를 1로 설정하고 이름이 1 자보다 긴 것으로 호출합니다. 실행 realloc()
하면 스택에 대한 포인터로 호출 을 시도 할 때 프로그램이 거의 확실하게 충돌 합니다.
(2010 년 12 월 27 일의 이전 답변)
KeithB의 코드에 대한 중요한 변경 사항 : 버퍼는 malloc에 의해 할당되거나 NULL로 지정되어야합니다. 스택에 할당하지 마십시오.
그 상태도 확인하는 것이 좋습니다.
나는 찾지 못했습니다 HAVE_CXA_DEMANGLE
. __GNUG__
코드가 컴파일된다는 보장은 없지만 확인 합니다. 누구든지 더 좋은 아이디어가 있습니까?
#include <cxxabi.h>
const string demangle(const char* name) {
int status = -4;
char* res = abi::__cxa_demangle(name, NULL, NULL, &status);
const char* const demangled_name = (status==0)?res:name;
string ret_val(demangled_name);
free(res);
return ret_val;
}
#include <cxxabi.h>
. 그렇지 않으면 잘 작동했습니다. 감사합니다.