未解析的外部符号,即使一切正常
Unresolved external symbol even if everything seems OK
我不习惯在 Windows 上编码,我对 VS 上的这个错误感到困惑。
我正在开发一个静态库 libA
,另一个 libB
调用 libA
中的一些方法,还有一个程序 prog
调用 [=12= 中的一些方法].
libA
编译没有任何问题。
libB
相同。关于libA
的include和lib文件夹给VS,还有libA.lib
作为附加依赖。
对于prog
,我给出了关于libA
和libB
的include和lib文件夹。这两个库本身作为附加依赖项提供。它可以编译,但是在链接时,我遇到了一些类型为 LNK2001 的错误:
unresolved external symbol "public virtual void __thiscall libA::classA1::methodA1(void)" (?methodA1@classA1@libA@@UEAXXZ) in File libB.lib(classB1.obj)
我做了 libB
的 dumpbin 并且符号 ?methodA1@classA1@libA@@UEAXXZ
在转储文件中多次出现。
Dump of file .\libB.lib
File Type: LIBRARY
Archive member name at 8: /
61C9303F time/date Mon Dec 27 12:17:19 2021
uid
gid
0 mode 36987E size correct header end
14630 public symbols
...
3F43C3C ?methodA1@classA1@libA@@UEAXXZ
...
Archive member name at 3698C2: /
61C9303F time/date Mon Dec 27 12:17:19 2021
uid
gid
0 mode 36272A size correct header end
61 offsets
...
32 ?methodA1@classA1@libA@@UEAXXZ
...
SECTION HEADER #42 .text$mn name
0 physical address
0 virtual address
1D7 size of raw data
5FA3 file pointer to raw data (00005FA3 to 00006179)
617A file pointer to relocation table
0 file pointer to line numbers
D number of relocations
0 number of line numbers 60501020 flags
Code
COMDAT; sym= "public: virtual void __cdecl libA::classA1::methodA1(void)" (?methodA1@classA1@libA@@UEAAXXZ)
16 byte align
Execute Read
...
SECTION HEADER #92
.xdata name
0 physical address
0 virtual address
1C size of raw data
6B4E file pointer to raw data (00006B4E to 00006B69)
6B6A file pointer to relocation table
0 file pointer to line numbers
1 number of relocations
0 number of line numbers
40301040 flags
Initialized Data
COMDAT; sym= $unwind$?methodA1@classA1@libA@@UEAAXXZ
4 byte align
Read Only
...
SECTION HEADER #93
.pdata name
0 physical address
0 virtual address
C size of raw data
6B74 file pointer to raw data (00006B74 to 00006B7F)
6B80 file pointer to relocation table
0 file pointer to line numbers
3 number of relocations
0 number of line numbers
40301040 flags
Initialized Data
COMDAT; sym= $pdata$?methodA1@classA1@libA@@UEAAXXZ
4 byte align
Read Only
...
RELOCATIONS #93
Symbol Symbol
Offset Type Applied To Index Name
-------- ---------------- ----------------- -------- ------
00000000 ADDR32NB 00000000 124 $LN269
00000004 ADDR32NB 000001D7 124 $LN269
00000008 ADDR32NB 00000000 22A $unwind$?methodA1@classA1@libA@@UEAAXXZ
...
RELOCATIONS #101
Symbol Symbol
Offset Type Applied To Index Name
-------- ---------------- ----------------- -------- ------
00000000 ADDR64 00000000 00000000 3BA ??_R4classA1@libA@@6B@ (const libA::classA1::`RTTI Complete Object Locator')
00000008 ADDR64 00000000 00000000 D3 ??_EclassA1@libA@@UEAAPEAXI@Z (public: virtual void * __cdecl libA::classA1::`vector deleting destructor'(unsigned int))
00000010 ADDR64 00000000 00000000 8D _purecall
00000018 ADDR64 00000000 00000000 8D _purecall
00000020 ADDR64 00000000 00000000 CE ?methodA1@classA1@libA@@UEAAXXZ (public: virtual void __cdecl libA::classA1::methodA1(void))
00000028 ADDR64 00000000 00000000 CF ?methodA2@classA1@libA@@UEAAXXZ (public: virtual void __cdecl libA::classA1::methodA2(void))
...
0CE 00000000 SECT42 notype () External | ?methodA1@classA1@libA@@UEAAXXZ (public: virtual void __cdecl libA::classA1::methodA1(void))
...
22A 00000000 SECT92 notype Static | $unwind$?methodA1@classA1@libA@@UEAAXXZ
22B 00000000 SECT93 notype Static | .pdata
Section length C, #relocs 3, #linenums 0, checksum AAAF74B1, selection 5 (pick associative Section 0x42)
22D 00000000 SECT93 notype Static | $pdata$?methodA1@classA1@libA@@UEAAXXZ
22E 00000000 SECT94 notype Static | .voltbl
Section length 4, #relocs 0, #linenums 0, checksum D5442740, selection 5 (pick associative Section 0x42)
libA
的 dumplib 文件也是如此。
如果有帮助,这里是 prog
的链接器命令:
/OUT:"C:\prog\Release\prog.exe" /MANIFEST /LTCG:incremental /NXCOMPAT /PDB:"C:\prog\Release\prog.pdb" /DYNAMICBASE "libA.lib" "libB.lib" "some_other_libs.lib" /DEBUG /MACHINE:X86 /OPT:REF /SAFESEH /INCREMENTAL:NO /PGD:"C:\prog\Release\prog.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Release\prog.exe.intermediate.manifest" /LTCGOUT:"Release\prog.iobj" /OPT:ICF /ERRORREPORT:PROMPT /ILK:"Release\prog.ilk" /NOLOGO /TLBID:1
终于找到问题了
libA 和 libB 在 Linux 上正常工作,所以我不明白为什么我在 Windows 上遇到这个问题。
事实证明,我真的不知道为什么,但是 CMake 生成的 VS 解决方案文件允许使用 x86 目标架构编译 libA,但在命令行中加上附加选项“/machine x64”部分(项目属性 > 链接器(或静态库的库管理器)> 命令行)。
我删除了这个“/machine x64”选项,重新编译了 libA,现在整个编译和链接都完成了。
我不习惯在 Windows 上编码,我对 VS 上的这个错误感到困惑。
我正在开发一个静态库 libA
,另一个 libB
调用 libA
中的一些方法,还有一个程序 prog
调用 [=12= 中的一些方法].
libA
编译没有任何问题。
libB
相同。关于libA
的include和lib文件夹给VS,还有libA.lib
作为附加依赖。
对于prog
,我给出了关于libA
和libB
的include和lib文件夹。这两个库本身作为附加依赖项提供。它可以编译,但是在链接时,我遇到了一些类型为 LNK2001 的错误:
unresolved external symbol "public virtual void __thiscall libA::classA1::methodA1(void)" (?methodA1@classA1@libA@@UEAXXZ) in File libB.lib(classB1.obj)
我做了 libB
的 dumpbin 并且符号 ?methodA1@classA1@libA@@UEAXXZ
在转储文件中多次出现。
Dump of file .\libB.lib
File Type: LIBRARY
Archive member name at 8: /
61C9303F time/date Mon Dec 27 12:17:19 2021
uid
gid
0 mode 36987E size correct header end
14630 public symbols
...
3F43C3C ?methodA1@classA1@libA@@UEAXXZ
...
Archive member name at 3698C2: /
61C9303F time/date Mon Dec 27 12:17:19 2021
uid
gid
0 mode 36272A size correct header end
61 offsets
...
32 ?methodA1@classA1@libA@@UEAXXZ
...
SECTION HEADER #42 .text$mn name
0 physical address
0 virtual address
1D7 size of raw data
5FA3 file pointer to raw data (00005FA3 to 00006179)
617A file pointer to relocation table
0 file pointer to line numbers
D number of relocations
0 number of line numbers 60501020 flags
Code
COMDAT; sym= "public: virtual void __cdecl libA::classA1::methodA1(void)" (?methodA1@classA1@libA@@UEAAXXZ)
16 byte align
Execute Read
...
SECTION HEADER #92
.xdata name
0 physical address
0 virtual address
1C size of raw data
6B4E file pointer to raw data (00006B4E to 00006B69)
6B6A file pointer to relocation table
0 file pointer to line numbers
1 number of relocations
0 number of line numbers
40301040 flags
Initialized Data
COMDAT; sym= $unwind$?methodA1@classA1@libA@@UEAAXXZ
4 byte align
Read Only
...
SECTION HEADER #93
.pdata name
0 physical address
0 virtual address
C size of raw data
6B74 file pointer to raw data (00006B74 to 00006B7F)
6B80 file pointer to relocation table
0 file pointer to line numbers
3 number of relocations
0 number of line numbers
40301040 flags
Initialized Data
COMDAT; sym= $pdata$?methodA1@classA1@libA@@UEAAXXZ
4 byte align
Read Only
...
RELOCATIONS #93
Symbol Symbol
Offset Type Applied To Index Name
-------- ---------------- ----------------- -------- ------
00000000 ADDR32NB 00000000 124 $LN269
00000004 ADDR32NB 000001D7 124 $LN269
00000008 ADDR32NB 00000000 22A $unwind$?methodA1@classA1@libA@@UEAAXXZ
...
RELOCATIONS #101
Symbol Symbol
Offset Type Applied To Index Name
-------- ---------------- ----------------- -------- ------
00000000 ADDR64 00000000 00000000 3BA ??_R4classA1@libA@@6B@ (const libA::classA1::`RTTI Complete Object Locator')
00000008 ADDR64 00000000 00000000 D3 ??_EclassA1@libA@@UEAAPEAXI@Z (public: virtual void * __cdecl libA::classA1::`vector deleting destructor'(unsigned int))
00000010 ADDR64 00000000 00000000 8D _purecall
00000018 ADDR64 00000000 00000000 8D _purecall
00000020 ADDR64 00000000 00000000 CE ?methodA1@classA1@libA@@UEAAXXZ (public: virtual void __cdecl libA::classA1::methodA1(void))
00000028 ADDR64 00000000 00000000 CF ?methodA2@classA1@libA@@UEAAXXZ (public: virtual void __cdecl libA::classA1::methodA2(void))
...
0CE 00000000 SECT42 notype () External | ?methodA1@classA1@libA@@UEAAXXZ (public: virtual void __cdecl libA::classA1::methodA1(void))
...
22A 00000000 SECT92 notype Static | $unwind$?methodA1@classA1@libA@@UEAAXXZ
22B 00000000 SECT93 notype Static | .pdata
Section length C, #relocs 3, #linenums 0, checksum AAAF74B1, selection 5 (pick associative Section 0x42)
22D 00000000 SECT93 notype Static | $pdata$?methodA1@classA1@libA@@UEAAXXZ
22E 00000000 SECT94 notype Static | .voltbl
Section length 4, #relocs 0, #linenums 0, checksum D5442740, selection 5 (pick associative Section 0x42)
libA
的 dumplib 文件也是如此。
如果有帮助,这里是 prog
的链接器命令:
/OUT:"C:\prog\Release\prog.exe" /MANIFEST /LTCG:incremental /NXCOMPAT /PDB:"C:\prog\Release\prog.pdb" /DYNAMICBASE "libA.lib" "libB.lib" "some_other_libs.lib" /DEBUG /MACHINE:X86 /OPT:REF /SAFESEH /INCREMENTAL:NO /PGD:"C:\prog\Release\prog.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Release\prog.exe.intermediate.manifest" /LTCGOUT:"Release\prog.iobj" /OPT:ICF /ERRORREPORT:PROMPT /ILK:"Release\prog.ilk" /NOLOGO /TLBID:1
终于找到问题了
libA 和 libB 在 Linux 上正常工作,所以我不明白为什么我在 Windows 上遇到这个问题。
事实证明,我真的不知道为什么,但是 CMake 生成的 VS 解决方案文件允许使用 x86 目标架构编译 libA,但在命令行中加上附加选项“/machine x64”部分(项目属性 > 链接器(或静态库的库管理器)> 命令行)。
我删除了这个“/machine x64”选项,重新编译了 libA,现在整个编译和链接都完成了。