Ubuntu20.04下ANTLR4 C++ demo运行触发__gthread错误求助
问题描述
- 运行环境:VirtualBox 虚拟机内 Ubuntu 20.04 系统,使用 g++ 9.4.0 编译器完成 ANTLR4 C++ 运行时编译
- 故障现象:编译 ANTLR4 自带 demo 过程无报错,运行生成的 ELF 文件时在 Lexer 初始化阶段崩溃,初步判断为
__gthread未正常启动 - 已做排查:检查项目 CMakeLists.txt 未发现 gthread 包的链接配置,系统为全新安装的 Ubuntu 20.04
gdb 调试输出如下:
Breakpoint 1, main () at /home/zhao/Downloads/antlr4/runtime/Cpp/demo/Linux/main.cpp:22 22 int main(int , const char **) { (gdb) n 23 ANTLRInputStream input(u8"🍴 = 🍐 + \"😎\";(((x * π))) * µ + ∰; a + (x * (y ? 0 : 1) + z);"); (gdb) n 24 TLexer lexer(&input); (gdb) s antlrcpptest::TLexer::TLexer (this=0x7fffffffdb20, input=0x7fffffffda50) at /home/zhao/Downloads/antlr4/runtime/Cpp/demo/generated/TLexer.cpp:171 171 TLexer::TLexer(CharStream *input) : Lexer(input) { (gdb) n 172 TLexer::initialize(); (gdb) s antlrcpptest::TLexer::initialize () at /home/zhao/Downloads/antlr4/runtime/Cpp/demo/generated/TLexer.cpp:272 272 void TLexer::initialize() { (gdb) s 273 std::call_once(tlexerLexerOnceFlag, tlexerLexerInitialize); (gdb) s std::call_once<void (&)()> (__once=..., __f=@0x7fffffffda00: {void (void)} 0x7fffffffda00) at /usr/include/c++/9/mutex:666 666 call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) (gdb) s 670 auto __callable = [&] { (gdb) 675 __once_callable = std::__addressof(__callable); // NOLINT: PR 82481 (gdb) std::__addressof<std::call_once<void (&)()>(std::once_flag&, void (&)())::{lambda()#1}>(void (&)()) (__r=...) at /usr/include/c++/9/bits/move.h:47 47 __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT (gdb) 48 { return __builtin_addressof(__r); } (gdb) std::call_once<void (&)()> (__once=..., __f=@0x55555556b4c3: {void (void)} 0x55555556b4c3 <(anonymous namespace)::tlexerLexerInitialize()>) at /usr/include/c++/9/mutex:675 675 __once_callable = std::__addressof(__callable); // NOLINT: PR 82481 (gdb) 676 __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; (gdb) std::call_once<void (&)()>(std::once_flag&, void (&)())::{lambda()#2}::operator void (*)()() const (this=0x7fffffffda00) at /usr/include/c++/9/mutex:676 676 __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; (gdb) std::call_once<void (&)()> (__once=..., __f=@0x55555556b4c3: {void (void)} 0x55555556b4c3 <(anonymous namespace)::tlexerLexerInitialize()>) at /usr/include/c++/9/mutex:683 683 int __e = __gthread_once(&__once._M_once, &__once_proxy); (gdb) __gthread_once (__once=0x5555556e32bc <(anonymous namespace)::tlexerLexerOnceFlag>, __func=0x7ffff7eabc20 <__once_proxy>) at /usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h:699 699 if (__gthread_active_p ()) (gdb) s __gthread_active_p () at /usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h:252 252 return __gthread_active_ptr != 0; (gdb) display __gthread_active_ptr 1: __gthread_active_ptr = (void * const) 0x0 (gdb) n 253 } 1: __gthread_active_ptr = (void * const) 0x0 (gdb) n __gthread_once (__once=0x5555556e32bc <(anonymous namespace)::tlexerLexerOnceFlag>, __func=0x7ffff7eabc20 <__once_proxy>) at /usr/include/x86_64-linux-gnu/c++/9/bits/gthr-default.h:699 699 if (__gthread_active_p ()) 1: __gthread_active_ptr = (void * const) 0x0 (gdb) n 702 return -1; 1: __gthread_active_ptr = (void * const) 0x0 (gdb) n 703 } 1: __gthread_active_ptr = (void * const) 0x0 (gdb) n std::call_once<void (&)()> (__once=..., __f=@0x55555556b4c3: {void (void)} 0x55555556b4c3 <(anonymous namespace)::tlexerLexerInitialize()>) at /usr/include/c++/9/mutex:690 690 if (__e) 1: __gthread_active_ptr = (void * const) 0x0 (gdb) n 691 __throw_system_error(__e);
故障原因
__gthread_active_ptr 为空不是系统依赖缺失导致的,全新安装的 Ubuntu 20.04 只要安装了 build-essential 和 g++ 就已经包含全部线程相关依赖,不需要额外安装软件包。
该报错本质是编译链接阶段没有正确关联 POSIX 线程库,导致 libstdc++ 的 gthread 兼容层找不到 pthread 实现,std::call_once 执行时直接返回错误触发异常。
解决步骤
- 修改 demo 目录下的 CMakeLists.txt,添加线程库依赖配置:
# 查找系统线程库 find_package(Threads REQUIRED) # 链接到目标可执行文件,注意把 antlr4-demo 替换成实际的编译目标名 target_link_libraries(antlr4-demo PRIVATE antlr4_static Threads::Threads )
不要手动硬编码
-lpthread链接参数,使用 CMake 官方提供的Threads::Threads目标可以自动适配不同平台的线程实现,避免兼容问题。
- 清理旧的编译缓存,重新编译:
# 进入 ANTLR4 C++ 运行时的 build 目录,或自行创建的 demo 编译目录 rm -rf * cmake .. make -j$(nproc)
- 重新运行生成的可执行文件即可正常执行,不会再触发 gthread 相关崩溃。
内容的提问来源于stack exchange,提问作者AshZhao
相关产品推荐
相关产品推荐

