gcc可通过-l链接libpci.a,g++为何提示函数未定义引用?
问题描述
基于Linux系统开发应用时使用pciutils库,按README执行以下命令编译仓库生成头文件和静态库libpci.a:
make PREFIX=./local install-lib
编译完成后,用g++编译测试程序test.cpp时出现链接错误:
g++ test.cpp -Ipciutils/local/include/pci -Lpciutils/local/lib -lpci -lz -ludev
错误提示:undefined reference to 'pci_alloc()'。
已确认libpci.a存在于./pciutils/local/lib目录,且通过nm -C libpci.a验证库中包含pci_alloc()函数。但将编译命令改为gcc编译test.c(test.c与test.cpp内容完全一致)时,编译成功:
gcc test.c -Ipciutils/local/include/pci -Lpciutils/local/lib -lpci -lz -ludev
测试代码内容:
#include <stdio.h> #include <pci.h> int main(void) { struct pci_access *pacc; pacc = pci_alloc(); /* Get the pci_access structure */ return 0; }
原因分析
核心差异在于C和C++的函数名修饰规则不同:
- pciutils是纯C语言实现的库,编译生成的静态库中,函数名保持C语言的原始名称(如
pci_alloc)。 - g编译C代码时,会对函数名进行名字修饰(Name Mangling):它会根据函数的参数类型、个数等信息修改函数名,以此支持C++的函数重载特性。比如原本的
pci_alloc()会被修饰成类似_Z9pci_allocv的名称。 - 链接阶段,g++会用修饰后的名字去
libpci.a中查找,自然找不到原始的C风格函数名,因此报未定义引用错误。 - 而gcc编译C代码时,不会对函数名进行修饰,直接用原始名称查找,所以能匹配到库中的函数。
解决方案
在C代码中包含pci.h时,用extern "C"包裹头文件,告诉g这部分代码遵循C语言的函数调用约定和命名规则,不要对其中的函数名进行修饰:
#include <stdio.h> extern "C" { #include <pci.h> } int main(void) { struct pci_access *pacc; pacc = pci_alloc(); return 0; }
之后再用原来的g++命令编译即可成功。
内容的提问来源于stack exchange,提问作者W.Lee
相关产品推荐
相关产品推荐

