C++指针无故损坏数据,AST节点返回赋值后打印异常求助
问题原因
核心是*悬挂指针(野指针)*问题,你在parseBinaryOperation中存储的左右子节点指针指向的是临时栈对象,对象生命周期结束后指针直接失效:
res.children.operator_op.left = &left;中的left是parseBinaryOperation的传值参数,属于函数栈上的临时对象,函数返回后这块栈内存会被系统回收,地址变为非法res.children.operator_op.right = &right;中的right是函数内定义的局部栈变量,同样在函数返回后内存被回收,地址失效
函数内打印正常是因为此时栈内存还没有被后续操作覆写,函数返回后上层函数的调用栈操作会覆盖这块内存,读取就会输出异常乱码。
修复方案
核心是让AST节点的生命周期和整棵AST树绑定,不要指向栈临时对象,常见两种实现方式:
方案1:改用值存储而非指针存储(适合AST节点体积不大的场景)
直接修改ast_node结构体定义,把operator_op里的左右子节点从指针改成普通的ast_node值成员,赋值的时候直接拷贝即可,不需要取地址:// 原结构体定义(假设) // struct operator_op { // ast_node* left; // ast_node* right; // }; // 修改后 struct operator_op { ast_node left; ast_node right; }; // 对应parseBinaryOperation内的赋值修改为 res.children.operator_op.left = left; res.children.operator_op.right = right;方案2:堆分配存储节点(用智能指针管理,适合AST节点体积大、有多态派生需求的场景)
用std::unique_ptr<ast_node>或std::shared_ptr<ast_node>管理节点内存,所有AST节点都在堆上分配,从根源避免栈临时对象的生命周期问题:// 修改operator_op成员为智能指针 struct operator_op { std::unique_ptr<ast_node> left; std::unique_ptr<ast_node> right; }; // 对应parseBinaryOperation修改为转移所有权 ast_node Parser::parseBinaryOperation(std::unique_ptr<ast_node> left) { ast_node res; auto curr_operator = current_token; res.token = curr_operator; res.kind = AST_OPERATOR; res.children.operator_op.left = std::move(left); sexp += curr_operator.keyword; advance(); auto currentPrecedence = precidence_map[tk_type]; auto right = std::make_unique<ast_node>(parseExpression(currentPrecedence)); res.children.operator_op.right = std::move(right); return res; } // 上层调用时也对应调整为传递堆分配的节点即可
如果不想修改结构体定义,也可以把上层传过来的left和局部的right手动拷贝到堆上再存地址,但是一定要配套对应的内存释放逻辑避免内存泄漏,更推荐使用上面两种成熟方案。
内容的提问来源于stack exchange,提问作者user14618630
相关产品推荐
相关产品推荐

