在编译时(或运行时)获取c ++函数的错误名称

iam*_*ter 13 c++ name-mangling

我有一个函数类方法,ValueHolder :: printValue

class ValueHolder {

public:
    void printValue ();
} ;
Run Code Online (Sandbox Code Playgroud)

如何在编译时(或运行时)确定其损坏的名称.

例如,我想这样做:

const char *mangled_name = GetMangledNameOfSymbol(&ValueHolder::printValue);
Run Code Online (Sandbox Code Playgroud)

此函数可能返回如下字符串:

"_ZN11ValueHolder10printValueEv"
Run Code Online (Sandbox Code Playgroud)

根据@Marco A.先决条件是现代编译器.一个支持typeid,并打开标志以启用此功能.

我也会接受一个可以为Gcc&Clang实用的答案,以及一个MSVC的存根.

Mar*_* A. 9

据说,没有标准的方法可以做到这一点 [lib.type.info]

类type_info描述了实现生成的类型信息.此类的对象有效地存储指向该类型的名称的指针,以及适合于比较两种类型的相等或整理顺序的编码值.类型的名称,编码规则和整理顺序都是未指定的,并且可能在程序之间有所不同.

您可以使用您的编译器实现,typeid(type/expression).name()但无法指定或强制执行此名称(它是实现定义的).它还取决于使用的编译标志(感谢malat).

例:

class ValueHolder {

public:
  void printValue();
};


int main() {
  std::cout << typeid(&ValueHolder::printValue).name();
}
Run Code Online (Sandbox Code Playgroud)

gcc7.0

M11ValueHolderFvvE

clang4.0

M11ValueHolderFvvE

MSVC14

void(__ cdecl ValueHolder ::*)(void)__ ptr64

  • 另请澄清,它不仅取决于编译器 + 版本,还取决于编译标志(例如 std=c++11 和 std::string 和/或诸如“-DGLIBCXX_DEBUG”之类的东西) (2认同)

iam*_*ter 5

我会添加一个答案,但我不会将其标记为正确。它并不完整。太大,无法添加为评论。这是我可以做的事情,但我正在寻找更好的方法。而且,是的,非常俗气。但我认为某个地方有一些 API,虽然仍然有点粗糙,但可以保证工作(如果在整个项目中使用单个编译器)。

template<typename R, typename C, typename... A>
struct MemberFunctionPointer
{
    typedef R Return;
    typedef C Class;
};

template<typename R, typename C, typename... A>
constexpr auto inferMemberFunctionPointer(R (C::*method)(A...))
{
    return MemberFunctionPointer<R,C,A...>{};
}

template<typename M, M m, typename... A>
class GenerateMethodSignature
{
    typedef typename decltype(inferMemberFunctionPointer(m))::Class T;
    typedef typename decltype(inferMemberFunctionPointer(m))::Return R;


public:
    static const char *mangledName (const char *fs)
    {
        const char *ts = typeid(T).name();
        const char *rs = typeid(R).name();
        const char *ms = typeid(M).name();

        std::string r = "_Z";
        if (ts[0] != 'N')
            r += "N";
        r += ts;
        if (ts[0] == 'N')
            r.pop_back();

        r += std::to_string(strlen(fs));
        r += fs;
        r += "E";

        r += ms + strlen ("M") + strlen(ts) + strlen ("F") + strlen(rs);
        r.pop_back();

        printf("calculated signature %s\n", r.c_str());

        // this is very bad but... for demonstration purposes
        return strdup(r.c_str());
    }
} ;

namespace MyNamespace {
namespace MySubNamespace {
class MyClass
{
public:
    int MyFunction (int myarg);
} ;
} // namespace
} // namespace

#define ExportSignature(T, M) GenerateMethodSignature<decltype(&T::M), &T::M>::mangledName(#M)
const char *myMethodSignature = ExportSignature(MyNamespace::MySubNamespace::MyClass, MyFunction);
Run Code Online (Sandbox Code Playgroud)


小智 1

那么你可以做的是使用 g++ 编译你的 C++ 程序并获取 .o 文件。对由此获得的 .o 文件运行“nm”命令以获取损坏的名称!该方法在Linux系统上是可行的。