在分析用GHC编写的Haskell程序时,类型类函数的名称在.prof文件中被破坏,以区分一个实例的实现与另一个实例的实现.如何解析这些名称以找出它是哪种类型的实例?
例如,假设我有以下程序,其中类型Fast
和Slow
两者都实现Show
:
import Data.List (foldl')
sum' = foldl' (+) 0
data Fast = Fast
instance Show Fast where
show _ = show $ sum' [1 .. 10]
data Slow = Slow
instance Show Slow where
show _ = show $ sum' [1 .. 100000000]
main = putStrLn (show Fast ++ show Slow)
Run Code Online (Sandbox Code Playgroud)
我编译-prof -auto-all -caf-all
并运行+RTS -p
.在生成的.prof文件中,我看到最高成本中心是:
COST CENTRE MODULE %time %alloc
show_an9 Main 71.0 83.3
sum' Main 29.0 16.7
Run Code Online (Sandbox Code Playgroud)
在树中,我同样看到(省略不相关的行): …
我正在研究一个DLL,它将使用_stdcall调用对话从另一种语言(因此没有导入库和包括dll的头文件)中使用.问题是VC++似乎总是对其导出的符号进行一些名称修饰.我见过的所有引用都说使用extern"C",但这似乎仍然留下了一个前导下划线,并且在导出的名称之后加了一个@加号.
最糟糕的一点是在目标语言中加载扩展dll的自动方式基本上是"func_name = GetProcAddress(dll,"func_name")"所以使用未修饰的名称GetProcAddress失败,并使用装饰名称它抱怨非法变量名称( @ 不被允许) :(
如何让VC++导出一些没有名字装饰的东西呢?
extern "C" __declspec(dllexport) int __stdcall test(int x, const char *str);
Run Code Online (Sandbox Code Playgroud)
DUMPBIN.EXE
00011366 _test @ 8 = @ ILT + 865(_test @ 8)
我试图将32位dll(和应用程序)移植到64位,我已经设法构建它没有错误.当我尝试使用我的64位应用程序加载它时,我注意到导出的函数名称不同.这是我导出函数的方式:
#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) long __stdcall Connect(char * name, long size);
#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)
在Dependency Walker中,导出的函数具有以下格式:
32位: _Connect@8
64位: Connect
在使用dll的应用程序中,我显式加载了dll(LoadLibrary成功)但GetProcAddress因64位而失败,因为它找不到具有提供名称的函数.
在我们的应用程序中,我保留函数名称如下:
#define ConnectName "_Connect@8"
...
GetProcAddress(Dll, ConnectName);
Run Code Online (Sandbox Code Playgroud)
所以我想知道是否可以为32位和64位dll导出相同的函数名称,或者这是一个坏主意?或者我需要在我的应用程序中执行以下操作:
#if _WIN64
#define ConnectName "Connect"
#else
#define ConnectName "_Connect@8"
#endif
Run Code Online (Sandbox Code Playgroud)
我感谢任何帮助.
如何在C++中查看编译器生成的重载函数的受损名称?我正在使用VC9,但欢迎其他编译器的答案.
编辑:我发现这里的所有答案都很有用.接受我最喜欢的那个.
我正在尝试构建一个我拥有的项目,它有几个导出的函数.函数遵循stdcall约定,如果用GCC编译,它们会被破坏
Func@X
Run Code Online (Sandbox Code Playgroud)
其他编译器破坏了这样的名称:
_Func@X
Run Code Online (Sandbox Code Playgroud)
有什么方法可以强制GCC将导出函数的名称破坏到后面的例子中吗?
好的,所以我可以使用dumpbin.exe/exports library.dll来查找dll中的所有方法.
...但是我如何找出传递给他们的参数?当然没有头文件.
使用Visual Studio 2010/2012,可以使用/FAs
开关编译c ++源文件,以生成生成的代码的程序集输出.但是生成的asm文件包含其错位形式的所有符号.
是否有开关或其他智能方法使Visual Studio生成未拼写的符号?我知道可以通过手动提供asm文件,undname.exe
但是切换比自定义的后期构建事件更方便.
我有一些代码,其中包含以下行
#pragma comment(linker, "/include:_test@12")
Run Code Online (Sandbox Code Playgroud)
当我使用配置类型为32位的C++ Visual Studio 2010编译代码时,使用此代码的项目工作正常(我也在32位Windows机器上).
当我将机器更改为64位并使用使用C++ Visual Studio 2010编译的x64配置时,我收到链接错误.
对于32位和64位,C++名称是否有所不同?如果是这样,我在哪里可以找到64位C++名称修改约定?
假设我有两个具有相同参数类型和名称的函数(不在同一个程序中):
std::string foo(int x) {
return "hello";
}
int foo(int x) {
return x;
}
Run Code Online (Sandbox Code Playgroud)
一旦编译,它们会具有相同的损坏名称吗?
是 C++ 中重整名称的返回类型部分吗?
使用c ++模板时,我们经常会得到很长的错误名称
_ZN11__sanitizer13InternalAllocEmPNS_28SizeClassAllocatorLocalCacheINS_20SizeClassAllocator32ILm0ELy140737488355328ELm0ENS_12SizeClassMapILm3ELm4ELm8ELm17ELm64ELm14EEELm20ENS_15TwoLevelByteMapILy32768ELy4096ENS_20NoOpMapUnmapCallbackEEES5_EEEEm
这在名义上很明显很好,并且易于调试,但是当我使用大型自定义类型(具有大型命名空间)时,由于名称错误,最终会出现非常大的二进制文件; 有些工具(如valgrind)甚至有一个符号名称最大长度,几乎不可能进行分析.
我想知道是否有办法让g ++/clang ++使用自定义的修改函数(比如md5),这样很长的符号变得 5c66b1073e1b453900bd7d32cb79fc0e
更短.