[英]Segmentation fault caused after iterating through a queue. Possibly caused by unique_ptr?
当我运行自动完成 function 时,我不断收到段错误。
gdb 给出以下段错误错误:
Program received signal SIGSEGV, Segmentation fault.
std::__uniq_ptr_impl<cs19::CompactStringSet::Node, std::default_delete<cs19::CompactStringSet::Node> >::_M_ptr (this=0x8) at /usr/include/c++/11/bits/unique_ptr.h:173
173 pointer _M_ptr() const { return std::get<0>(_M_t); }
要发布的内容很多,要查看的代码的主要部分就在注释说// step 3
to end 之后。 我包括 rest 主要是为了上下文。
在我的 function std::get<0>
是一个指针。 段错误可能是由于pop()
造成的,尽管在 gdb 中,它在获得段错误之前对一个元素执行了pop()
。 我正在使用我不太熟悉的unique_ptrs
,我知道它们应该自动删除,但我可能在实现中出错。 错误出现在while(sibling->sibling)
处。
function 预计通过以child/sibling
方式链接的字符数据集 go 并返回最快匹配的std::vector
,但不超过n
。
我知道 seg 故障不是一成不变的,所以我不期待一个确切的答案,任何帮助!
std::vector<std::string> CompactStringSet::autocomplete(const std::string& base, std::size_t n) const {
// check children, if no match -> check siblings, if no match -> return empty vector; after
// all matches to base, check all base->child->sibling then check each ->child
// each option, add any which evaluate to terminal. Exit after n have been found,
// or no options remain
std::vector<std::string> results;
std::queue<std::pair<const Node*, std::string>> matches;
const Node* cur = &this->root_;
std::size_t numResults = 0;
// step 1 : READ IN BASE, MAKE SURE IT'S VALID
for (auto let : base) {
if (cur->child) {
if (cur->child->letter == let) {
cur = cur->child.get();
continue;
}
}
Node* sibling = cur->child.get();
while (sibling->sibling) {
sibling = sibling->sibling.get();
if (sibling->letter == let) {
cur = sibling;
continue;
}
}
return results;
}
// step 2 : start from after base and check options make sure if terminal
// and initialize queue
if (cur->child) {
std::string toAdd = base + cur->child->letter;
auto newElem = std::make_pair(cur->child.get(), toAdd);
matches.push(newElem);
}
Node* newSibling = cur->child.get();
while (newSibling->sibling) {
newSibling = newSibling->sibling.get();
std::string toAdd = base + newSibling->letter;
auto newElem = std::make_pair(newSibling, toAdd);
matches.push(newElem);
}
// step 3 : check each node*, if terminal add to results
do {
// check first in queue
auto elem = matches.front();
auto curNode = std::get<0>(elem);
auto curStr = std::get<1>(elem);
if (std::get<0>(elem)->terminal) {
results.push_back(std::get<1>(elem));
++numResults;
}
if (curNode->child) {
std::string updated = curStr + curNode->child->letter;
auto newElem = std::make_pair(curNode->child.get(), updated);
matches.push(newElem);
}
Node* sibling = curNode->child.get();
while (sibling->sibling) { // where error message occured
sibling = sibling->sibling.get();
std::string updated = curStr + sibling->letter;
auto newElem = std::make_pair(sibling, updated);
matches.push(newElem);
}
matches.pop();
} while (numResults < n && matches.size() > 0);
return results;
}
我怀疑错误在这里:
if (cur->child) {
if (cur->child->letter == let) {
cur = cur->child.get();
continue;
}
}
Node* sibling = cur->child.get();
while (sibling->sibling) {
特别是,上面引用的第一行中的if (cur->child) {
测试表明代码作者知道cur->child
可能是 null unique_ptr
,并且正在防范这种可能性。 很公平。 但就在下面,我们有这段代码将sibling
设置为等于(无论cur->child
指向什么,作为原始指针)并尝试在下一行取消引用sibling
。 在这种情况下,如果cur->child
是NULL
,那么sibling
也将是 NULL,因此尝试评估兄弟 - sibling->sibling
会导致段错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.