未定义对“__gxx_personality_sj0”的引用

undefined reference to `__gxx_personality_sj0`

提问人:smallB 提问时间:10/13/2011 最后编辑:Богуслав ПавлишинецьsmallB 更新时间:2/13/2020 访问量:41241

问:

使用 gcc 4.6 尝试执行此代码时:

   #include <iostream>

using namespace std;

#include <bitset>

int main()
{
   //Int<> a;
   long long min = std::numeric_limits<int>::min();
   unsigned long long max = std::numeric_limits<int>::max();
   cout << "min: " << min << '\n';
   cout << "max: " << max << '\n';
   cout << (min <= max);
   std::bitset<64> minimal(min);
   cout << "minimal: " << minimal;

   return 0;
}

我收到以下错误:
1.未定义对 2 的
引用。未定义对 3 的
引用。未定义对 4 的
引用。未定义对
__gxx_personality_sj_Unwind_SjLj_Register_Unwind_SjLj_Unregister_Unwind_SjLj_Resume

这到底是怎么回事?!

C++ GCC 链接器错误 undefined-reference

评论

0赞 Björn Pollex 10/13/2011
请发布一个完整的示例,我们可以为编译器提供重现错误。请参见 sscce.org
1赞 Björn Pollex 10/13/2011
@Mystical:这是一个链接器错误。C 编译器在解析过程中会抱怨。
0赞 Björn Pollex 10/13/2011
这不会编译,你必须.#include <limits>
0赞 ks1322 10/13/2011
与这个问题非常相似 http://stackoverflow.com/q/2189681/72178
0赞 Björn Pollex 10/13/2011
GCC 4.3.4 编译、链接和运行它很好

答:

31赞 Mankarse 10/13/2011 #1

这些函数是 GCC 的 C++ 异常处理支持的一部分。GCC 支持两种异常处理,一种基于对 setjmp 和 longjmp 的调用(sjlj 异常处理),另一种基于 DWARF 调试信息格式(DW2 异常处理)。

当您尝试在单个可执行文件中混合使用不同的异常处理实现编译的对象时,就会发生这些类型的链接器错误。您似乎正在使用 DW2 GCC,但您尝试使用的某些库是使用 sjlj 版本的 GCC 编译的,从而导致这些错误。

简短的回答是,这类问题是由不同编译器之间的 ABI 不兼容引起的,因此,当您混合使用不同编译器编译的库或使用同一编译器的不兼容版本时,就会发生这种情况。

评论

11赞 smallB 10/13/2011
我解决了这个问题。我犯错的是,在工具链中,作为编译器,我有 i686-pc-mingw32-gcc-4.6.0.exe,但作为链接器:mingw32-g++.exe。我已将其更改为 i686-pc-mingw32-g++.exe 并解决了问题。谢谢。
0赞 Jonathan Wakely 6/4/2015
@Alex,除了这个答案不能解决问题。OP 的错误是由于根本没有链接到 libstdc++ 引起的,而不是由于链接到不兼容的 libstdc++ 引起的。
3赞 Alex 6/4/2015
@JonathanWakely请重新阅读 smallB 的评论,它说 gcc 被用作编译器,g++ 被用作链接器,根据您的解释,它应该已经链接了 libstdc++。smallB 还提到,将 g++ 版本切换到 i686 版本后,“问题就解决了”。
0赞 Javid 5/21/2016
很好的答案,解决了我的问题。我使用的是 CodeBlocks 安装的 mingw-g++,而不是我安装:D
2赞 nmgeek 8/6/2017
虽然这个答案不是针对原始问题,但它可以帮助那些带着同样错误来到这里的人。就我而言,我在 ubuntu 14 上构建了一个存档库,并尝试在 Windows 上链接到它,运行 mingw-w64 编译器的 her 版本。在 Windows 上安装 mingw-64 时,您可以选择下载 she 或 sjlj 版本。但是当你使用 apt-get 在 Ubuntu 上安装它时,你会得到 apt 存储库中的版本。Ubuntu 14 配置了 sjlj 版本,Ubuntu 16 配置了 she 版本。
10赞 Ben 11/8/2012 #2

以防万一其他人有这个问题:我在为我的项目创建文件后更改了编译器。.o

当我重新构建同一个项目时,新的编译器没有构建新文件,因此它们缺少一些关键信息。删除旧文件并重建后,错误已修复。.o

我认为从头开始重建,没有删除,工作方式是一样的。

评论

2赞 George Menoutis 2/7/2021
这个答案被严重低估了,在疯狂搜索后修复了所有那些未定义的参考线。
12赞 n611x007 8/10/2014 #3

正如 smallB 在评论中指出的那样,您可能使用了 ,专注于程序,但您有一个程序。gccCC++

要编译程序,请确保改用编译器驱动程序!C++g++

例:

坏:gcc -o foo.exe foo.cpp

好: g++-o foo.exe foo.cpp

评论

2赞 Jonathan Wakely 6/4/2015
不太准确,只是一个运行正确编译器的驱动程序程序,对于 or 文件,它将运行 C++ 编译器。但与驱动程序不同的是,它不会自动链接到 C++ 标准库。当然,这在手册中有所记录。gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.htmlgcc.cpp.ccg++
0赞 n611x007 6/5/2015
@JonathanWakely信息量最大的,我喜欢你的评论!亲切的触摸,让像我这样的孩子变得轻松。我已经更新了我的答案,目的是让它更准确。我也故意让它保持简单。根据琐事,文档中大约有 288715 个单词 - 显然!;)C
3赞 Jonathan Wakely 6/4/2015 #4

该命令只是一个驱动程序,它为您提供的源文件运行正确的编译器(或者,如果您为其提供目标文件,则运行链接器)。对于具有已知文件扩展名的 C++ 源文件,它将运行 C++ 编译器(对于 GCC 称为 )并正确编译代码。gcccc1plus

它不会自动链接到 C++ 标准库(GCC 称为 )。libstdc++

若要解决此问题,需要通过在链接时添加到选项来显式链接到该库,或者只是编译并使用驱动程序进行链接,这会自动添加到链接器选项中。-lstdc++g++-lstdc++

因此,您可以使用来编译 C++ 程序,但是如果您使用标准库或 C++ 运行时的任何功能(包括异常处理),则需要使用 (或仅用于运行时) 链接到 C++ 运行时。使用会自动为您执行此操作。gcc-lstdc++-lsupc++g++

这记录在手册中:https://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html

评论

1赞 rogerdpack 2/24/2018
是的,这解决了它。根本不是“不匹配的 SLJL 和 DWARF”之间的问题,它只是将 c 程序链接到一些 c++ 库,因此添加 -lstdc++ 修复了它)。谢谢!还要确保它“追随”需要它的其他库,并确保正在运行的确切命令包含它:)
0赞 Misha Taylor 2/13/2020 #5

使用 minGW-g++.exe 而不是 gcc.exe 看看现在会发生什么。

评论

0赞 stdunbar 2/13/2020
为什么这个答案比 8 年前的答案更好?它也提到了 mingw 编译器。