【问题标题】:Deciphering Mangled C++ names $$F破译 Mangled C++ 名称 $$F
【发布时间】:2018-05-10 04:06:20
【问题描述】:

我的非托管 c++ 类中有以下函数调用:

_pUserApi = CThostFtdcMdApi::CreateFtdcMdApi();

编译器似乎正在生成这个符号:

?CreateFtdcMdApi@CThostFtdcMdApi@@$$FSAPEAV1@PEBD_N1@Z

但是当我对链接的 .lib 文件执行转储时,我看到了这个符号:

?CreateFtdcMdApi@CThostFtdcMdApi@@SAPEAV1@PEBD_N1@Z

不同的是第一个里面多了一个$$F。

是否存在可以解释这种差异的编译器选项?...是否有任何类型的参考来破译重整?

注意:这是一个 x64 库文件(我正在使用 x64 进行编译。

完全错误:

Error   LNK2028 unresolved token (0A000021) 
"public: static class CThostFtdcMdApi * __cdecl CThostFtdcMdApi::CreateFtdcMdApi(char const *,bool,bool)" 
(?CreateFtdcMdApi@CThostFtdcMdApi@@$$FSAPEAV1@PEBD_N1@Z) 
referenced in function "public: void __cdecl CTPMarketData::Start(char const *,char const *,char const *,char const *)" 
(?Start@CTPMarketData@@$$FQEAAXPEBD000@Z)
CTPLib_cpp

完整的 DumpBin:

  61C __IMPORT_DESCRIPTOR_thostmduserapi
  862 __NULL_IMPORT_DESCRIPTOR
  9A0 thostmduserapi_NULL_THUNK_DATA
  D94 ?CreateFtdcMdApi@CThostFtdcMdApi@@SAPEAV1@PEBD_N1@Z
  D94 __imp_?CreateFtdcMdApi@CThostFtdcMdApi@@SAPEAV1@PEBD_N1@Z
  E2C ?GetApiVersion@CThostFtdcMdApi@@SAPEBDXZ
  E2C __imp_?GetApiVersion@CThostFtdcMdApi@@SAPEBDXZ
  C0E ??1CThostFtdcMdApi@@IEAA@XZ
  C0E __imp_??1CThostFtdcMdApi@@IEAA@XZ
  B8E ??0CThostFtdcMdApi@@QEAA@XZ
  B8E __imp_??0CThostFtdcMdApi@@QEAA@XZ
  B08 ??0CThostFtdcMdApi@@QEAA@AEBV0@@Z
  B08 __imp_??0CThostFtdcMdApi@@QEAA@AEBV0@@Z
  C8E ??4CThostFtdcMdApi@@QEAAAEAV0@AEBV0@@Z
  C8E __imp_??4CThostFtdcMdApi@@QEAAAEAV0@AEBV0@@Z
  D18 __imp_??_7CThostFtdcMdApi@@6B@

Visual Studio 生成的命令行:

d:\Program Files(x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.14.26428\bin\HostX86\x86\CL.exe / c / AI"C:\Program Files ( x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.6.1\" / AI"C:\Program Files (x86)\Windows Kits\10\References" / AI"C:\Program Files (x86)\Reference Assemblies \Microsoft\Framework.NETFramework\v4.6.1\Facades\" / Zi / clr / nologo / W3 / WX - / diagnostics:classic / Od / Oy - / D WIN32 / D _DEBUG / D _WINDLL / D _UNICODE / D UNICODE / EHa / MDd / GS / fp : 精确 / Zc : wchar_t / Zc : forScope / Zc : inline / Yu"stdafx.h" / Fp"Debug\CTPLib_cpp.pch" / Fo"Debug\" / Fd"Debug\vc141。 pdb" / TP / FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.6.1\mscorlib.dll" / FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\ Framework.NETFramework\v4.6.1\System.Data.dll" / FU"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.6.1\System.dll" / FU"C:\Program文件 (x86)\参考汇编blies\Microsoft\Framework.NETFramework\v4.6.1\System.Xml.dll"/analyze-/FC/errorReport:prompt/clr:nostdlib AssemblyInfo.cpp CTPMarketData.cpp CTPMarketDataWrapper.cpp CTPSpi.cpp

【问题讨论】:

  • 您能否发布信息,例如正在使用的工具链(命令行程序的版本比 Visual Studio 版本更精确)以及用于编译和链接程序和链接的命令行选项图书馆?
  • 我不知道该库(不是我的)...但我的默认选项(在配置属性> C/C++ > 命令行> 所有选项中)是:/Yu" stdafx.h" /GS
  • 不确定 是关于什么的......但这就是它向我展示的内容。
  • 此外,Agner Fog 编写了令人印象深刻的各种 C++ 编译器名称修饰算法的文档:agner.org/optimize/calling_conventions.pdf。不幸的是,我看不到 Microsoft C++ 的$$F 序列在该文档中的位置(但我当然可能会错过它——名称修饰配方很复杂)。也许这是新事物?
  • 而且是VS 2017……我创建了一个Visual C++ CLR库……但是调用这个函数的类是一个非托管类。

标签: c++ linker-errors


【解决方案1】:

Microsoft 编译器带有一个 undname 实用程序:

与 $$F:

C:\>undname ?CreateFtdcMdApi@CThostFtdcMdApi@@$$FSAPEAV1@PEBD_N1@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?CreateFtdcMdApi@CThostFtdcMdApi@@$$FSAPEAV1@PEBD_N1@Z"
is :- "public: static class CThostFtdcMdApi * __ptr64 __cdecl CThostFtdcMdApi::CreateFtdcMdApi(char const * __ptr64,bool,bool)"

没有:

c:\>undname ?CreateFtdcMdApi@CThostFtdcMdApi@@SAPEAV1@PEBD_N1@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?CreateFtdcMdApi@CThostFtdcMdApi@@SAPEAV1@PEBD_N1@Z"
is :- "public: static class CThostFtdcMdApi * __ptr64 __cdecl CThostFtdcMdApi::CreateFtdcMdApi(char const * __ptr64,bool,bool)"

不幸的是,undname 将两者解码为相同的函数签名。更多的挖掘是为了......

PS:GCC 的等效工具是c++filt

【讨论】:

    【解决方案2】:

    所以...它确实是本机库和 CLR 库之间的区别。当使用 CLR 库进行调用时,它会将 $$F 插入到损坏的名称中,但当调用是从本机库中进行时则不会。

    有趣的是...我在创建对象的本机库中创建了一个类/函数...修复了它...另外我能够从 CLR 库代码中调用其他成员函数并且有效!

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题。我有一个带有非虚拟方法的抽象基类。 CLR 无法链接到非虚拟方法,但是当我将函数更改为虚拟时它起作用了!

      所以$$f 与虚拟方法有关,但名称unmangler 并没有这样显示。

      【讨论】:

        猜你喜欢
        • 2023-03-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-24
        • 2022-06-11
        • 1970-01-01
        • 1970-01-01
        • 2015-03-13
        相关资源
        最近更新 更多