Được sự chú ý của câu hỏi/câu trả lời này và phản hồi có giá trị từ GManNickG, tôi đã xóa mã một chút. Hai phiên bản được đưa ra: một phiên bản với các tính năng C++ 11 và một phiên bản khác chỉ có các tính năng C++ 98.
Trong tệp loại.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
Trong file type.cpp (yêu cầu 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
Cách sử dụng:
#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;
}
It in:
Loại ptr_base: Base*
Loại pointee: Derived
Tested với g ++ 4.7.2, g ++ 4.9.0 20.140.302 (thử nghiệm), kêu vang ++ 3.4 (trunk 184.647), Clang 3,5 (trunk 202.594) trên Linux 64 bit và g ++ 4.7.2 (Mingw32, Win32 XP SP2).
Nếu bạn không thể sử dụng C++ 11 tính năng, đây là cách nó có thể được thực hiện trong C++ 98, file type.cpp bây giờ là:
#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
(cập nhật từ tháng 8, 2013)
The accepted answer (as of Sep 7, 2013), khi cuộc gọi đến abi::__cxa_demangle()
thành công, trả về một con trỏ tới một mảng cục bộ, được phân bổ ngăn xếp ... ouch!
Cũng lưu ý rằng nếu bạn cung cấp bộ đệm, abi::__cxa_demangle()
giả sử nó được cấp phát trên heap. Phân bổ bộ đệm trên ngăn xếp là lỗi (từ tài liệu gnu): "Nếu output_buffer
không đủ dài, nó sẽ được mở rộng bằng cách sử dụng realloc
".Gọi realloc()
trên con trỏ tới ngăn xếp ... ouch! (Xem thêm Igor Skochinsky 's comment bình luận.)
Bạn có thể dễ dàng xác minh cả hai lỗi này: chỉ cần giảm kích thước bộ đệm trong câu trả lời được chấp nhận (tính đến ngày 7 tháng 9 năm 2013) từ 1024 xuống nhỏ hơn, ví dụ 16, và đặt tên cho nó có tên không phải là dài hơn 15 (vì vậy realloc()
là không phải là được gọi). Tuy nhiên, tùy thuộc vào hệ thống của bạn và tối ưu hóa trình biên dịch, đầu ra sẽ là: garbage/nothing/program crash.
Để xác minh lỗi thứ hai: đặt kích thước bộ đệm thành 1 và gọi nó bằng tên có độ dài hơn 1 ký tự. Khi bạn chạy nó, chương trình gần như chắc chắn đổ vỡ khi nó cố gắng gọi realloc()
với một con trỏ đến ngăn xếp.
(Câu trả lời cũ từ tháng 27, 2010)
thay đổi quan trọng thực hiện để KeithB's code: bộ đệm đã được hoặc được phân bổ bởi malloc hoặc quy định như NULL. KHÔNG phân bổ nó trên ngăn xếp.
Bạn cũng nên kiểm tra trạng thái đó.
Tôi không thể tìm thấy HAVE_CXA_DEMANGLE
. Tôi kiểm tra __GNUG__
mặc dù điều đó không đảm bảo rằng mã thậm chí sẽ biên dịch. Bất cứ ai có một ý tưởng tốt hơn?
#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;
}
Lưu ý rằng điều này cần '' #include ''. Nếu không làm việc tuyệt vời, cảm ơn. –
jterrace
Rất tiếc, xin lỗi. Cố định và cảm ơn! – Ali
Bạn có thể giải thích tại sao bộ đệm không thể được cấp phát trên ngăn xếp không? Bởi vì cho đến nay nó đã làm việc tốt cho tôi. – terminus