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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 23:27:03