NoViableAltException 异常引起的 coredump 问题
使用antlr4解析时,在遇到 NoViableAltException 异常的时候,有些情况下会遇到 coredump 错误,如果仅仅抛出异常还好,但是出现崩溃问题在项目中就是大问题了,这个必须得找到并解决。
antlr4 解析时,在 ParserATNSimulator.cpp 中的 execATN 函数的 179 行,和 execATNWithFullContext 函数的 345 行,都会调用
NoViableAltException e = noViableAlt();
// 创建 NoViableAltException 对象
179:
NoViableAltException e = noViableAlt(input, outerContext, previousD->configs.get(), startIndex, false);
NoViableAltException 中的 _deleteConfigs
的值为 false,析构函数为
~NoViableAltException() {
if (_deleteConfigs)
delete _deadEndConfigs;
}
354:
NoViableAltException e = noViableAlt(input, outerContext, previous, startIndex, previous != s0);
因为 previous != s0
,所以 _deleteConfigs
的值为 true,所以析构的时候会 delete _deadEndConfigs
。
此时,在 DefaultErrorStrategy.cpp:148
行,
recognizer->notifyErrorListeners(..., std::make_exception_ptr(e))
std::make_exception_ptr
Creates anstd::exception_ptr
that holds a reference to a copy ofe
.
参数为保持 NoViableAltException 拷贝的一个引用的变量(std::exception_ptr)。如果 NoViableAltException 被析构了,那么其所指向的 _deadEndConfigs
指针也会被释放,但是 NoViableAltException 这个变量在后面还会被释放一次,造成 double free 的程序崩溃。
这里只需要将 354 行按照 179 行一样,将函数最后一个参数设置为 false 即可。
因为不懂 antlr4 原理,那部分代码也没有看懂,作者为什么抛出那样的异常不是很明白,也就没法修改了。我提了一个 issue,感兴趣的可以关注一下