Bu sorunun / cevabın gördüğü ilgi ve GManNickG'den gelen değerli geri bildirimler göz önüne alındığında, kodu biraz temizledim. İki sürüm verilmiştir: biri C ++ 11 özellikli ve diğeri yalnızca C ++ 98 özellikli.
Dosya type.hpp içinde
#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
Dosya type.cpp'de (C ++ 11 gerektirir)
#include "type.hpp"
#ifdef __GNUG__
#include <cstdlib>
#include <memory>
#include <cxxabi.h>
std::string demangle(const char* name) {
int status = -4;
std::unique_ptr<char, void(*)(void*)> res {
abi::__cxa_demangle(name, NULL, NULL, &status),
std::free
};
return (status==0) ? res.get() : name ;
}
#else
std::string demangle(const char* name) {
return name;
}
#endif
Kullanım:
#include <iostream>
#include "type.hpp"
struct Base { virtual ~Base() {} };
struct Derived : public Base { };
int main() {
Base* ptr_base = new Derived();
std::cout << "Type of ptr_base: " << type(ptr_base) << std::endl;
std::cout << "Type of pointee: " << type(*ptr_base) << std::endl;
delete ptr_base;
}
Aşağıdakileri yazdırır:
Ptr_base türü: Pointe Base*
türü:Derived
Linux 64 bit üzerinde g ++ 4.7.2, g ++ 4.9.0 20140302 (deneysel), clang ++ 3.4 (trunk 184647), clang 3.5 (trunk 202594) ve g ++ 4.7.2 (Mingw32, Win32 XP SP2) ile test edilmiştir.
C ++ 11 özelliklerini kullanamıyorsanız, C ++ 98'de şu şekilde yapılabilir, dosya type.cpp şu anda:
#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;
handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );
return (status==0) ? result.p : name ;
}
#else
std::string demangle(const char* name) {
return name;
}
#endif
(8 Eylül 2013'ten itibaren güncelleme)
Kabul edilen yanıt (7 Eylül 2013 itibariyle) , çağrı abi::__cxa_demangle()
başarılı olduğunda, yerel, yığın ayrılmış diziye bir işaretçi döndürür ... ouch!
Ayrıca bir arabellek sağlarsanız abi::__cxa_demangle()
, yığın üzerinde tahsis edileceğini varsaydığını unutmayın . Tamponun yığın üzerine tahsis edilmesi bir hatadır (gnu belgesinden): " output_buffer
Yeterince uzun değilse, kullanılarak genişletilir realloc
." Yığına realloc()
bir işaretçi çağırmak ... ah! (Ayrıca Igor Skochinsky'nin nazik yorumuna bakın.)
Sadece örnek 16 için, daha küçük bir şeye 1024 den (7 Eyl 2013 itibariyle) kabul cevap tampon boyutunu küçültmek ve bir adla o şey vermek: Kolayca bu hataların ikisi doğrulamak değil bu yüzden (uzun 15'ten realloc()
olduğunu değil ) olarak adlandırılan. Yine de, sisteminize ve derleyici optimizasyonlarına bağlı olarak çıktı şu olacaktır: çöp / hiçbir şey / program çökmesi.
İkinci hatayı doğrulamak için: tampon boyutunu 1 olarak ayarlayın ve adı 1 karakterden uzun olan bir şeyle çağırın. Çalıştırdığınızda, program realloc()
yığına bir işaretçi ile çağrı yapmaya çalışırken neredeyse kesinlikle çöküyor .
(27 Aralık 2010 tarihli eski cevap)
KeithB kodunda yapılan önemli değişiklikler : arabellek ya malloc tarafından tahsis edilmeli ya da NULL olarak belirtilmelidir. Onu yığına tahsis ETMEYİN.
Bu durumu da kontrol etmek akıllıca olacaktır.
Ben bulamadılar HAVE_CXA_DEMANGLE
. Kontrol ettim, __GNUG__
ancak bu kodun derleneceğini garanti etmiyor. Daha iyi bir fikri olan var mı?
#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>
. Aksi takdirde harika çalıştı, teşekkürler.