gpt4 book ai didi

c++ - 使用共享指针时释放后堆的使用

转载 作者:行者123 更新时间:2023-12-05 05:30:27 24 4
gpt4 key购买 nike

当我尝试将共享指针传递给类对象时,出现免费错误后,我一直在使用堆。

首先,我的树构建器将根作为私有(private)字段:

class ExpressionTree{
private:
std::shared_ptr<ASTNode> root;
public:
std::shared_ptr<ASTNode> getRoot();
void build(std::string expression);
}

供引用的ASTNode:

class ASTNode {
public:
virtual ~ASTNode() = default;
virtual void accept(ASTVisitor& visitor, ElementMap elements) = 0;
};

构建函数(使用调车场算法)将节点存储在出队中:

 std::deque<std::shared_ptr<ASTNode>> nodeStack;
std::deque<std::string> operatorStack;

例如,对于二元运算符(从 ASTNode 派生的类):

auto right = nodeStack.back();
nodeStack.pop_back();
auto left= nodeStack.back();
nodeStack.pop_back();

root = std::make_shared<BinaryOperator>(operatorStack.back(), left, right);
operatorStack.pop_back();
nodeStack.emplace_back(std::move(root));

调车场算法遍历所有token后,我移动根:

root = std::move(nodeStack.back());

我有一个游戏“规则” vector (存储为字符串),我试图将它们存储到我拥有的 "Rule" 类中。问题出在 "When" 规则中。我的解释器是我使用树构建器并构建“When”对象的地方:

ExpressionTree expressionTree;
for (auto rule: rules_from_json->getVector()){
if(ruleName == "when"){
std::vector<std::pair<std::shared_ptr<ASTNode>, RuleVector>> conditionExpressionRulePairs;

ElementVector cases = rule->getMapElement("cases")->getVector();
for(auto caseRulePair : cases){

std::string conditionString = caseRulePair->getMapElement("condition")->getString();
expressionTree.build(conditionString);
std::shared_ptr<ASTNode> conditionExpressionRoot = expressionTree.getRoot();

RuleVector caseRules;
toRuleVec(game, caseRulePair->getMapElement("rules"), caseRules);
conditionExpressionRulePairs.push_back({conditionExpressionRoot, caseRules});
}

ruleObject = std::make_shared<When>(conditionExpressionRulePairs);
}
} //freed here

错误表明 std::shared_ptr 在上述代码段的最后一个大括号处被释放。

这是 when 规则:

class When : public Rule {
std::shared_ptr<ASTNode> conditionRoot;

std::map<std::shared_ptr<ASTNode>, RuleVector> condition_rule_pairs;
std::map<std::shared_ptr<ASTNode>, RuleVector>::iterator condition_rule_pair;

RuleVector::iterator rule;
bool match = false;

public:
When(std::map<std::shared_ptr<ASTNode>, RuleVector>& conditon_rule_pairs);
bool executeImpl(ElementSptr element, ElementMap elementsMap) final;
void resetImpl() final;
};

所有其他规则都有效,并且能够正确地将访问者传递到根目录。这里唯一的区别是我将每个案例的根存储在一个 vector 中并将其传递给:

//rules.cpp in the `execute` function of the `when` rule
for (; conditionExpression_rule_pair != conditionExpression_rule_pairs.end(); conditionExpression_rule_pair++) {
conditionRoot = conditionExpression_rule_pair->first; //**this line gives the error**
conditionRoot->accept(resolver, elementsMap);

错误:

AddressSanitizer: heap-use-after-free on address 0x00010a902690 at pc 0x000104f83ec4 bp 0x00016b488550 sp 0x00016b488548
#0 0x104f83ec0 in std::__1::shared_ptr<ASTNode>::shared_ptr(std::__1::shared_ptr<ASTNode> const&) memory:3125
#1 0x104f687a4 in std::__1::shared_ptr<ASTNode>::shared_ptr(std::__1::shared_ptr<ASTNode> const&) memory:3127
#2 0x104f716b8 in std::__1::shared_ptr<ASTNode>::operator=(std::__1::shared_ptr<ASTNode> const&) memory:3246
#3 0x104f6fe34 in When::executeImpl(std::__1::shared_ptr<ListElement>, std::__1::map<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::shared_ptr<ListElement>, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const, std::__1::shared_ptr<ListElement> > > >) rules.cpp:105

问题是,我试图在构造函数中将访问者传递给根并且它有效:

When::When(std::vector<std::pair<std::shared_ptr<ASTNode>&,RuleVector>>& conditionExpression_rule_pairs)

: conditionExpression_rule_pairs(conditionExpression_rule_pairs),

conditionExpression_rule_pair(conditionExpression_rule_pairs.begin()),

rule(conditionExpression_rule_pair->second.begin()) {

TreePrinter t; //a visitor just to pretty print nodes
ElementMap elementsMap;
for(auto it : conditionExpression_rule_pairs){
it.first->accept(t, elementsMap);
std::cout << std::endl;

}
}

所以不知何故,根存在于 when constructor 但不在 when execute 中,因为它已从堆中释放。我怀疑这与根都存储在 vector 中这一事实有关,因为对于其他规则,我只是传入一个单数根,然后构造函数将它分配给另一个根,例如 foreach规则:

Foreach::Foreach(std::shared_ptr<ASTNode> listExpressionRoot, RuleVector _rules, std::string elementName)
: listExpressionRoot(listExpressionRoot), rules(_rules), elementName(elementName) {
}

foreach 中,我可以在 execute 函数中访问根并传递访问者,等等。

我尝试了所有方法,但似乎无法消除 when 规则中的这个错误。请帮忙。

最佳答案

我不敢相信。我为此花了一周时间,并在两个不同的论坛上发帖。

结果:

rule(conditionExpression_rule_pair->second.begin())

在 When 构造函数的初始化列表中,正在使用构造函数参数中的 conditionExpression_rule_pair:

When::When(std::vector<std::pair<std::shared_ptr<ASTNode>&,RuleVector>>& conditionExpression_rule_pairs)

而不是 when 规则中的实际字段。很明显,当构造函数超出范围并且迭代器将指向任何内容时, vector 被删除。

关于c++ - 使用共享指针时释放后堆的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74663942/

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