I keep getting a seg fault when I run an autocomplete function.
gdb gives the following seg fault error:
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); }
This is kind of a lot to post, the main part of the code to look at is right after the comment that says // step 3
to the end. I'm including the rest mostly for context.
In my function std::get<0>
is a pointer. The seg fault might be because of the pop()
, though in gdb it performed a pop()
on one element prior to getting the seg fault. I'm using unique_ptrs
which I'm not super familiar with, I know they're supposed to auto delete but I may be making errors in the implementation. The error is at while(sibling->sibling)
.
The function is expected to go through a dataset of chars which are linked in child/sibling
fashion and return a std::vector
of the fastest matches, but no more than n
.
I know seg faults aren't cut-and-dry so I don't expect an exact answer, anything helps!
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;
}
I suspect the error is here:
if (cur->child) {
if (cur->child->letter == let) {
cur = cur->child.get();
continue;
}
}
Node* sibling = cur->child.get();
while (sibling->sibling) {
In particular, the if (cur->child) {
test in the first line quoted above indicates that the code's author knows that cur->child
might be a null unique_ptr
, and is guarding against that possibility. Fair enough. But then just below that we have this code that sets sibling
equal to (whatever cur->child
points to, taken as a raw-pointer) and tries to dereference sibling
in the next line. In this case, if cur->child
was NULL
, then sibling
will also be NULL, and therefore trying to evaluate sibling->sibling
will cause a segfault.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.