我一直在寻找“导出符号”这个术语。导出符号在 C/C++ 中或相对于库(共享/静态)意味着什么?我们从哪里导出符号,为什么?导出符号与编译器名称修饰的关系是什么?
1 回答
导出符号意味着“宣传”它在您的目标文件/库中的存在以及它的位置,以便它可以被其他模块导入(=链接到)。
链接可以静态或动态完成,但无论哪种方式,链接器都必须知道符号是什么以及它在哪里,并且导出的符号和导入的符号必须匹配才能发生。名称修饰与此相关(C++ 名称修饰在符号名称中包含符号的类型定义,并且导出和导入符号的修饰必须匹配,链接器才能正确链接导入导出)。
例子:
假设您有一个库“STANDARDC”(随机名称)和您的程序 SOMEPROG。程序 SOMEPROG 需要打印到控制台,所以它会调用printf
. 但是您实际上并没有printf
在您的程序 SOMEPROG 中实现,您只是使用它(=导入它),而实现在其他地方。
库 STANDARDC 有一个它导出的符号列表,其中包括在该库中实现并且可以从外部调用的所有函数(=导出的函数)。printf
是这样的功能之一,所以它会出现在导出的列表中。
编译器通过您的 SOMEPROG.C 并看到您引用printf
,但没有实现它。编译器将 添加printf
到生成的 SOMEPROG.obj 的导入符号列表中,以便链接器将实际实现链接到其中。
链接器获取您的 SOMEPROG.obj 文件和 STANDARDC .lib 文件,并查看 SOMEPROG.obj 中使用了哪些函数。链接器发现它printf
没有实现,它被导入,所以链接器查看它拥有的所有 .lib 文件,并printf
在 STANDARDC 的导出列表中找到匹配项。它采用printf
from STANDARDC 的实现并将其链接到您引用导入符号的任何地方的程序中printf
。