ध्यान देने पर यह प्रश्न / उत्तर प्राप्त होता है, और 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*
प्रकार : सूचक का प्रकार:Derived
G ++ 4.7.2, g ++ 4.9.0 20140302 (प्रायोगिक), क्लैंग ++ 3.4 (ट्रंक 184647), क्लैंग 3.5 (ट्रंक 202594) लिनक्स 64 बिट और जी ++ 4.7.2 (मिंगव 32, 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
(अपडेट 8 सितंबर 2013 से)
स्वीकार किए गए उत्तर (7 सितंबर, 2013 के अनुसार) , जब कॉल abi::__cxa_demangle()
सफल होता है, तो एक पॉइंटर को एक स्थानीय, स्टैक आबंटित ऐरे ... रिटर्न के लिए लौटा देता है !
यह भी ध्यान दें कि यदि आप एक बफर प्रदान करते हैं, तो abi::__cxa_demangle()
मान लें कि इसे ढेर पर आवंटित किया जाना है। स्टैक पर बफर आवंटित करना एक बग (ग्नू डॉक से) है: "यदि output_buffer
लंबे समय तक पर्याप्त नहीं है, तो इसका उपयोग करके इसे विस्तारित किया जाता है realloc
।" एक पॉइंटर को स्टैक पर कॉल realloc()
करना ... ouch! ( इगोर स्कोकिंस्की की तरह की टिप्पणी भी देखें ।)
आप आसानी से इन कीड़ों के दोनों सत्यापित कर सकते हैं: सिर्फ बफर आकार स्वीकार किए जाते हैं जवाब में 1024 से छोटे कुछ करने के लिए, उदाहरण के लिए 16 को कम (7 सितं, 2013 के रूप में), और यह एक नाम के साथ कुछ देना नहीं 15 से अधिक समय (ताकि realloc()
है नहीं कहा जाता है)। फिर भी, आपके सिस्टम और संकलक अनुकूलन के आधार पर, आउटपुट होगा: कचरा / कुछ भी नहीं / प्रोग्राम क्रैश।
दूसरी बग को सत्यापित करने के लिए: बफर आकार को 1 पर सेट करें और इसे उस चीज़ के साथ कॉल करें जिसका नाम 1 वर्ण से अधिक लंबा है। जब आप इसे चलाते हैं, तो प्रोग्राम लगभग आश्वस्त हो जाता है क्योंकि यह realloc()
एक पॉइंटर को स्टैक के साथ कॉल करने का प्रयास करता है ।
(27 दिसंबर, 2010 से पुराना उत्तर)
कीथब के कोड में किए गए महत्वपूर्ण बदलाव : बफर को या तो मॉलोक द्वारा आवंटित किया जाना चाहिए या 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>
। अन्यथा महान काम किया, धन्यवाद।