使用GCC编译C++项目时出现operator delete未定义引用链接错误
问题解答
1. 为什么错误出现在链接阶段,而非编译阶段?
编译阶段仅负责对单个源文件做语法校验、语义解析,生成目标文件(.o),只要代码中用到的函数、运算符有对应的声明(来自头文件)即可编译通过,不需要找到实际的实现代码。
你报错里的operator delete(void*, unsigned long)、__cxa_throw_bad_array_new_length都是C标准库的实现符号,编译阶段只需要C标准头文件的声明就可以正常生成.o文件,只有到链接阶段,链接器才会去关联的库中查找这些符号的实际实现,找不到就会抛出undefined reference错误。
你遇到的问题本质是GCC版本不兼容:GCC 5之后新增了带size_t参数的operator delete重载,__cxa_throw_bad_array_new_length也是GCC 4.9之后才加入libstdc的符号,用高版本GCC编译生成的.o文件会依赖这些新符号,若链接时使用的libstdc版本低于编译用的GCC版本,就会找不到对应符号。你把GCC整体降到4.8.5之后,编译阶段就不会生成对这些高版本符号的引用,链接时用4.8.5对应版本的libstdc++就能找到所有符号,问题自然消失。
2. 如何定位缺失的库文件?
定位步骤如下:
- 先判断缺失符号的类型:如果是
operator new/delete、__cxa_开头的符号,均属于C++标准库libstdc++;如果是第三方库的API,可以直接搜索符号名确认归属的库。 - 确认链接参数中已经添加了对应库的链接指令(比如C++标准库对应
-lstdc++,线程库对应-lpthread等)。 - 确认当前工具链使用的库版本和编译用的编译器版本匹配:可以用
g++ -print-file-name=libstdc++.so查看当前GCC关联的libstdc++路径,再用nm -D <库路径> | grep <缺失的符号名>检查该库是否导出了对应的符号,比如你可以执行nm -D /usr/lib64/libstdc++.so.6 | grep "__cxa_throw_bad_array_new_length"验证符号是否存在。 - 如果是第三方库符号缺失,检查是否安装了对应库的开发包(比如CentOS下是*-devel包,Ubuntu下是*-dev包),开发包才会包含链接需要的.so文件和头文件。
3. 如何用pkg-config确定需要的库?
pkg-config的作用是自动读取库对应的配置文件(.pc文件),输出该库需要的编译参数、链接参数,避免手动写参数时遗漏或者顺序错误。
使用方法如下:
- 先根据缺失的符号确认归属的库,比如缺失ncurses相关的符号就对应ncurses库,缺失openssl相关符号对应libssl库。
- 检查系统中是否存在对应库的.pc文件,默认路径为
/usr/lib/pkgconfig、/usr/share/pkgconfig,如果找不到需要先安装对应库的开发包。 - 编译时添加
pkg-config --cflags <库名>获取编译参数,链接时添加pkg-config --libs <库名>获取链接参数,比如要链接ncurses就可以写gcc test.c -o test $(pkg-config --cflags --libs ncurses)。
注意你本次遇到的问题不是库缺失,是工具链版本不兼容,不需要用pkg-config处理。
内容的提问来源于stack exchange,提问作者Tiina
相关产品推荐
相关产品推荐

