Reputation: 11
So everything was working great until I decided to comment out a print method (for debugging). Once I commented it out, my code began to seg fault.
I assumed this was because I was somehow modifying something in my print method, so I commented out one line at a time so I could find where it was happening. After commenting every single line in the print out, I noticed it would seg fault only when I wasn't calling the print method (even if it was completely empty!).
So I did this:
void emptyMethod(Qclass c) {}
void Typechecker::initializeClasses(AST::Node *astRoot) {
...
Qclass clazz;
...
this->classes[clazz.name] = clazz;
emptyMethod(clazz); // I have no idea why I have to do this, but it
seg faults if I don't
...
}
This fixes my seg fault.
Structs in question:
struct Qclass; // forward declare
struct Qmethod {
AST::Node *node; // pointer to the node in the tree
// The reference to the containing class of a method is a pointer because
// it may not be fully initialized when passed into any given Qmethod.
// This is okay because we don't use *clazz until after all initialization is
complete.
Qclass *clazz;
std::string name;
std::vector<std::string> init;
std::map<std::string, std::string> type;
std::vector<AST::Node*> stmts;
};
struct Qclass {
AST::Node *node; // pointer to the node in the tree
std::string name;
std::string super;
Qmethod constructor;
std::vector<Qmethod> methods;
// for use in init before use checking in non constructor methods
std::vector<std::string> instanceVars;
};
Where it is seg faulting:
bool Typechecker::initCheckStmt(Qmethod &method, AST::Node *stmt, bool isConstructor) {
...
method.clazz->instanceVars.push_back(left->get(IDENT)->name); // seg faults here when not calling the empty method
...
return true;
}
Seg fault error:
#0 0x00007fffff1919b8 in std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char>
>::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&) () from /usr/lib/x86_64-linux-
gnu/libstdc++.so.6
#1 0x000000000041ab38 in void __gnu_cxx::new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#2 0x0000000000417dc6 in void std::allocator_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::construct<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#3 0x0000000000415b56 in std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::push_back(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) ()
#4 0x00000000004136b3 in Typechecker::initCheckStmt(Qmethod&, AST::Node*, bool) ()
#5 0x00000000004134b9 in Typechecker::getLeaves(Qmethod&, AST::Node*, std::vector<AST::Node*, std::allocator<AST::Node*> >&, bool) ()
#6 0x00000000004137c8 in Typechecker::initCheckQmethod(Qmethod&, bool) ()
#7 0x0000000000413a16 in Typechecker::initializeBeforeUseCheck() ()
#8 0x0000000000413d12 in Typechecker::checkProgram() ()
#9 0x0000000000426e7b in main ()
I can see it must have something to do with the instanceVars vector, but I don't understand why an empty method call would fix it. My Googling ability isn't helping me at all, so any pointers would be very much appreciated.
(this code is for a compilers course)
Upvotes: 0
Views: 713
Reputation: 1170
You've got yourself some undefined behavior. Your program is doing something—maybe an out-of-bounds memory access, who knows—that is throwing off your program. In C++, when your program does that, all bets are off for what it does next, including segfaulting.
That empty method call is hiding the bug, but it's not fixing the bug. As you correctly noted, that method call shouldn't affect whether it segfaults. The reason why it does is because of the undefined behavior.
To solvev this, you'll need to look at the rest of your program to determine where there might be an issue. Just the one line where it broke isn't enough; you should look before and after the line where it ends up segfaulting, as well as what you're passing into initializeClasses
.
Upvotes: 0