ANTLR4 C++运行时SingletonPredictionContext::equals段错误求助
ANTLR4 C++运行时段错误排查
问题描述
使用ANTLR4 C++运行时解析输入时触发段错误,相关代码及栈跟踪信息如下:
语法定义(MemMap.g4)
grammar MemMap; memmap: region+ EOF; region: (WORD | '_')+ WORD*; fragment LOWERCASE: [a-z]; fragment UPPERCASE: [A-Z]; WORD: [A-Za-z]+;
C++测试代码
int main() { ANTLRInputStream input("test_test , 0x0 , 0x1 , 4K , TEST , TEST , :R:W:X:8:16:32:64:"); MemMapLexer lexer(&input); CommonTokenStream tokens(&lexer); MemMapParser parser(&tokens); auto* p = parser.memmap(); // <-- 此调用触发段错误 }
栈跟踪信息
antlr4::atn::PredictionContext::getContextType PredictionContext.h:170 antlr4::atn::SingletonPredictionContext::equals SingletonPredictionContext.cpp:60 antlr4::atn::operator== PredictionContext.h:206 antlr4::atn::PredictionContextCache::PredictionContextComparer::operator() PredictionContextCache.cpp:55 std::__detail::_Equal_helper::_S_equals hashtable_policy.h:1460 std::__detail::_Hashtable_base::_M_equals hashtable_policy.h:1844 std::_Hashtable::_M_find_before_node hashtable.h:1562 std::_Hashtable::_M_find_node hashtable.h:649 std::_Hashtable::find hashtable.h:1452 std::unordered_set::find unordered_set.h:654 antlr4::atn::PredictionContextCache::get PredictionContextCache.cpp:40 getCachedContextImpl PredictionContext.cpp:53 antlr4::atn::PredictionContext::getCachedContext PredictionContext.cpp:520 antlr4::atn::ATNSimulator::getCachedContext ATNSimulator.cpp:32 antlr4::atn::ATNConfigSet::optimizeConfigs ATNConfigSet.cpp:138 antlr4::atn::ParserATNSimulator::addDFAState ParserATNSimulator.cpp:1335 antlr4::atn::ParserATNSimulator::addDFAEdge ParserATNSimulator.cpp:1287 antlr4::atn::ParserATNSimulator::computeTargetState ParserATNSimulator.cpp:324 antlr4::atn::ParserATNSimulator::execATN ParserATNSimulator.cpp:188 antlr4::atn::ParserATNSimulator::adaptivePredict ParserATNSimulator.cpp:163 antlr_memmap::MemMapParser::region() 0x000000000048b2f2 antlr_memmap::MemMapParser::memmap() 0x000000000048acdc
问题原因分析
词法规则缺失:语法中直接在解析器规则
region里使用字面量'_',但未显式定义对应的词法规则。输入中出现_(如test_test里的下划线)时,词法分析器无法匹配合法Token,生成INVALID_TOKEN。未处理的词法错误会导致解析器进入未定义行为,最终触发段错误。规则冗余引发状态爆炸:
region: (WORD | '_')+ WORD*规则存在冗余,(WORD | '_')+已经包含任意数量的字母和下划线组合,后续的WORD*完全多余。这种冗余规则会让解析器的ATN(增强转移网络)生成大量重复的预测上下文,在C++运行时的缓存逻辑中触发空指针访问,进而引发段错误。
解决方案
1. 修正语法定义
添加显式的下划线词法规则,并简化冗余的解析器规则:
grammar MemMap; memmap: region+ EOF; region: IDENTIFIER; // 使用统一的标识符规则 fragment LOWERCASE: [a-z]; fragment UPPERCASE: [A-Z]; IDENTIFIER: (WORD | '_')+; // 定义包含字母和下划线的标识符 WORD: [A-Za-z]+;
如果需要更严格的标识符规则(如必须以字母开头),可调整为:
IDENTIFIER: [A-Za-z] (WORD | '_')*;
2. 添加错误处理逻辑
在C++代码中添加错误监听器,捕获词法和语法错误,避免未定义行为:
#include "antlr4-runtime.h" #include "MemMapLexer.h" #include "MemMapParser.h" using namespace antlr4; int main() { ANTLRInputStream input("test_test , 0x0 , 0x1 , 4K , TEST , TEST , :R:W:X:8:16:32:64:"); MemMapLexer lexer(&input); lexer.addErrorListener(new DiagnosticErrorListener()); CommonTokenStream tokens(&lexer); MemMapParser parser(&tokens); parser.addErrorListener(new DiagnosticErrorListener()); auto* p = parser.memmap(); delete p; return 0; }
3. 处理输入中的其他非法字符
输入包含逗号、冒号、数字(如0x0、4K)等字符,当前语法未定义对应词法规则,同样会触发词法错误。若需解析这些内容,需补充对应规则:
COMMA: ','; COLON: ':'; HEX_NUMBER: '0x' [0-9A-Fa-f]+; SIZE: [0-9]+ [KMG];
内容的提问来源于stack exchange,提问作者Sustrak
相关产品推荐
相关产品推荐

