用g++-4.9.3 -std=c++11
代码编译完成后
#include <iostream>
#include <typeinfo>
using namespace std;
int main() { cout << typeid([]{}).name() << endl; }
Run Code Online (Sandbox Code Playgroud)
输出Z4mainEUlvE_
作为Linux x86_64上给定lambda的受损名称.但是,该c++filt
工具无法解开它.它只输出给它的输入,Z4mainEUlvE_
.
我怎么解开呢?
我试图导出一个简单的测试函数,用于处理一个应用程序(fyi:mIRC),它将调用约定指定为:
int __stdcall test_func(HWND mWnd, HWND aWnd, char *data, char *parms, BOOL show, BOOL nopause)
Run Code Online (Sandbox Code Playgroud)
现在,要从应用程序中调用它,我将使用test_func,但我注意到由于名称错误,它并不像我想象的那么简单.
通过类似的主题,我已经了解到将extern"C"与__declspec(dllexport)结合使用是一种等效的(某种程度上)方法,可以将重整数据删除到模块定义(.def).但是,当使用extern/dllexport方法时,我的函数(作为示例)始终是_test_func @ numbers,而.def删除了所有需要导出到的应用程序所需的修改.
有人可以解释一下这是为什么吗?我只是对这两种方法感到好奇.谢谢!
考虑以下功能:
template <typename A, typename B>
auto Min(A&& a, B&& b)
-> decltype(a < b ? std::forward<A>(a) : std::forward<B>(b))
{
return a < b ? std::forward<A>(a) : std::forward<B>(b);
}
Run Code Online (Sandbox Code Playgroud)
该片段Min(0, 1)
使模板被实例化为Min<int, int>
.奇怪的是,Min
我的代码使用g ++和clang的错误名称是_Z3MinIiiEDTqultfp_fp0_cl7forwardIT_Efp_Ecl7forwardIT0_Efp0_EEOS0_OS1_
(aka :) decltype (({parm#1}<{parm#2})?((forward<int>)({parm#1})) : ((forward<int>)({parm#2}))) Min<int, int>(int&&, int&&)
.换句话说,用于推断返回类型的表达式是受损名称的一部分.就我个人而言,我期望的东西会更加清晰:( _Z3MinIiiET_OS0_OT0_
又名:) int Min<int, int>(int&&, int&&)
.为什么不是这样?
似乎g ++只将decltype
表达式放在实际需要它的情况下,因为这些形式都是_Z3Maxii
:
auto Max(int x, int y) -> int
auto Max(int x, int y) -> decltype(0)
环顾四周,我看到的主要是关于解码C++符号而不是如何破坏它们的问题.是的,可以g++
使用该-S
选项调用包含要修改的符号的一些虚拟代码,然后检查生成的程序集,但是我无法找到关于GCC名称修改的良好引用或规范.我能找到的最接近的东西是http://www.int0x80.gr/papers/name_mangling.pdf,但它似乎没有涵盖名称模板实例化如何被破坏或为什么_Z3fooIN3BarEE3FooIXT_EEv
会被翻译成的东西Foo<Bar> foo<Bar>()
(尽管我可以善待看看怎么样,但到底是IXT_EE
什么?为什么在这个N
之后没有_Z
?这甚至意味着什么?).
Python 为类方法和属性提供私有名称修改.
是否有任何需要此功能的具体情况,或者它只是Java和C++的延续?
请描述一个应该使用Python名称修改的用例,如果有的话?
此外,我对作者仅仅试图防止意外外部属性访问的情况不感兴趣.我相信这个用例与Python编程模型不一致.
在分析用gcc编译的程序时,我注意到了像foo.isra.3
.有什么isra
表明?我注意到其中一个函数只在几个地方调用,其中一个参数总是指定为文字值.也许这意味着它是针对某些参数优化的函数的变体?
看一下C++程序的反汇编,我看到了类似的函数_Z41__static_initialization_and_destruction_0ii.constprop.221
.constprop
这种情况下的意思是什么?它看起来在外观上与isra后缀相似(有时结合起来,例如.isra.124.constprop.226
),但它意味着别的东西.
Itanium ABI 指定,有一些无趣的异常,返回类型包含在模板实例的错位名称中,但不包含在非模板中.
为什么是这样?在什么情况下,您可以有两个函数模板实例,其中链接器需要区分它们,因为它不表示单定义规则违规或类似?
作为我的意思的一个例子:
class ReturnType {};
class ParamType {};
template <typename T>
ReturnType foo(T p) {
return ReturnType();
};
template ReturnType foo<ParamType>(ParamType);
ReturnType bar(ParamType p) {
return ReturnType();
}
Run Code Online (Sandbox Code Playgroud)
然后生成的对象文件具有重整:
ReturnType foo<ParamType>(ParamType)
=> _Z3fooI9ParamTypeE10ReturnTypeT_
^^^^^^^^^^^^
ReturnType bar(ParamType)
=> _Z3bar9ParamType
Run Code Online (Sandbox Code Playgroud)
为什么foo
需要ReturnType
损坏但bar
不是?
(我假设有一个原因,这不仅仅是一个随意的选择.)
当我试图解决静态链接中的问题时,我_GLOBAL__sub_I_
在符号名称前面遇到了几个前缀.尽管我使用过,它仍然以那种形式出现nm --demangle(-C)
.
我偶然发现了这个答案(如何找到全局静态初始化).看看我的源代码,它确实看起来像一个全局静态变量的初始化.
我想知道的是,我在哪里可以获得有关__sub_和其他受损名称的更多信息__cxxabiv1
?
我有一个函数类方法,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的存根.