gpt4 book ai didi

c++ - 段。 std::unique_ptr 和 ctor 的错误

转载 作者:行者123 更新时间:2023-11-30 03:58:30 27 4
gpt4 key购买 nike

对于我实际实现的解析器,我在解析器中部分拥有这些私有(private)函数:

解析器私有(private)方法:

    Token const* current_token() const;
Token const* next_token();
Token const* peek_token();

std::unique_ptr<ast::Expression> parse_expression();
std::unique_ptr<ast::TypeSpecifier> parse_type_specifier();
std::unique_ptr<ast::VariableDeclarationStatement> parse_variable_declaration();
std::unique_ptr<ast::Statement> parse_function_definition();
std::unique_ptr<ast::Statement> parse_top_level_statement();

parse_variable_declaration 方法的实现是这样的:

parse_variable_declaration():

std::unique_ptr<ast::VariableDeclarationStatement> Parser::parse_variable_declaration() {
next_token(); // consume 'var'

if (current_token()->get_type() != TokenTypes::identifier) {
throw parser_error(current_token(), "", "expected identifier\n");
}
const auto id = current_token(); // store identifier
next_token(); // consume identifier

std::unique_ptr<ast::TypeSpecifier> type;
std::unique_ptr<ast::Expression> expr;

auto assignment_required = true;
if (current_token()->get_type() == TokenTypes::op_colon) { // optional type specifier
next_token(); // consume ':'

type = parse_type_specifier();
assignment_required = false;
}

if (assignment_required && current_token()->get_type() != TokenTypes::op_equals) {
throw parser_error(current_token(), "", "expected equals operator\n");
}

if (current_token()->get_type() == TokenTypes::op_equals) {
next_token(); // consume '='

expr = parse_expression();
}

if (current_token()->get_type() != TokenTypes::op_semi_colon) {
throw parser_error(current_token(), "", "expected semi-colon\n");
}

next_token(); // consume ';'

DEBUG_STDERR("parsed: variable_declaration_statement\n");
return std::make_unique<ast::VariableDeclarationStatement>(
id->get_string(), std::move(type), std::move(expr));
}

最后一行(返回)以段错误结束。它基本上调用了 VariableDeclarationStatement 的构造函数:

VariableDeclarationStatement 构造函数:

VariableDeclarationStatement::VariableDeclarationStatement(
std::string const& name,
std::unique_ptr<TypeSpecifier> type_specifier,
std::unique_ptr<Expression> expr
):
m_name{name},
m_type_specifier{std::move(type_specifier)},
m_expr{std::move(expr)}
{}

我从昨天开始调试这个东西,似乎无法找出为什么它不能按预期工作。我想构建带有指向其子节点的唯一指针的抽象语法树(解析器输出)(因为它们是其子节点的唯一所有者,这才有意义)——这就是我努力与它们合作的原因。

控制台输出:DEBUG_STDERR

parsed: primitive_type_int // from parse_type_specifier()
parsed: integral_expression // from parse_expression()
parsed: variable_declaration_statement
[1] 12638 segmentation fault (core dumped) ./cion_compiler

最佳答案

唯一指针的 move 操作基本上可以归结为简单的指针复制。 unique_ptr 的任何实现都没有理由在 move 它们的过程中取消对指针的引用。因此,此操作导致段错误的可能性几乎为零。

在您的返回语句/构造函数调用中,您确实有一个(或多个)非常明显的指针取消引用,作为 id->get_string() 调用的一部分。

首先,id 指针是这样创建的:

  const Token* const id = current_token(); // store identifier
next_token(); // consume identifier

除非保证 current_token() 返回的任何指针在时间结束前(或在当前解析操作的生命周期内)都有效,否则很有可能在调用 next_token() 之后,id 指针无效,即指向不存在或失效的 Token 对象。

即使 id 指针仍然指向一个现有的 Token 对象,它也有可能处于“僵尸”状态,并且从中获取一个字符串,通过get_string(),是一个无效的操作。

如果我是你,我会在那里寻找段错误的来源。您可能还想在(内存)调试器中运行它以获取它的源代码,它可能会将您指向 get_string 函数作为它的源代码,无论是在取消引用this 指针(id 指针)或在构造字符串本身期间。如果 get_stringToken 类中的虚拟函数,它还可以指向虚拟表查找。无论哪种方式,我都高度怀疑这是段错误的原因,因为它是您发布的代码中唯一明显危险的代码。

关于c++ - 段。 std::unique_ptr 和 ctor 的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27409088/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com