You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题原因分析

  1. 词法规则缺失:语法中直接在解析器规则region里使用字面量'_',但未显式定义对应的词法规则。输入中出现_(如test_test里的下划线)时,词法分析器无法匹配合法Token,生成INVALID_TOKEN。未处理的词法错误会导致解析器进入未定义行为,最终触发段错误。

  2. 规则冗余引发状态爆炸: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 17:54:54