链接错误:找不到__thiscall函数符号但定义了__cdecl函数符号

时间:2017-01-03 21:41:10

标签: c++ visual-studio linker cmake

我正在尝试使用Visual Studio 2012编译一个测试程序,该程序应链接到同事给我的test.lib文件。

编译在链接步骤停止,错误为LNK2019。缺少的符号是:

public: virtual __thiscall abc::Test::~Test(void)

使用实用程序dumpbin,我发现在test.lib中定义了以下符号:

public: virtual __cdecl abc::Test::~Test(void)

这两个功能有什么区别?我该如何解决这个编译问题?我错过了一些编译标志吗?

1 个答案:

答案 0 :(得分:1)

你没有错过旗帜。

Calling convention modifiers,例如__thiscall__cdecl,会在内部修改函数的名称。因此,__thiscall abc::Test::~Test(void) __cdecl abc::Test::~Test(void)具有相同的功能。要解决此问题,请将__thiscall更改为__cdecl

IIRC,__cdecl是MSVC(Visual Studio编译器)的默认调用约定,因此如果您的同事没有指定任何特殊内容,则dumpbin会将该函数描述为具有{__cdecl。 1}}调用约定。

<强>解释

与C不同,C ++函数,方法和对象的内部名称​​不与源文件中的相同。这称为name mangling(有时称为名称修饰)。名称修改允许重载函数,也就是说,有几个函数只有它们的参数类型,类/名称空间成员资格等不同。

假设我有以下C程序:

// Foo.c
#include <stdio.h>

void myPrint(void) {
    printf("Hello, World!\n");
}

void myPrint(const char* str) {
    printf(str);
}

int main() {
    myPrint();
    myPrint("Hello, World!\n");
}

如果您尝试将其编译为C代码:

$ gcc -o Foo Foo.c
Foo.c:7:6: error: redefinition of ‘myPrint’

但是如果你尝试将其编译为C ++:

$ g++ -o Foo Foo.c

它编译。<​​/ p>

如果您尝试使用g++ -o Foo.s Foo.cpp -S -Os查看程序集,您会发现void myPrint(void);函数的错位名称为_Z7myPrintv(最终v代表void),而void myPrint(const char*);函数的错位名称为_Z7myPrintPKcPKc:指向康斯坦特字母的指针)。

顺便说一句,函数的错位名称取决于您使用的编译器。使用MSVC(Visual Studio&#39; s编译器),void myPrint(const char*);具有以下错位名称:?myPrint@@YAXPBD@Z