Valgrind aborting with "pure virtual method called" long before the point where the program segfaults

Viewed 193

I'm trying to track down what's causing a segfault when I run my unittests.

When I run it through gdb, the program completes the block of tests in question, then throws a SIGABORT with the message "corrupted double-linked list." From the backtrace, I determined that the problem was occurring in the destructor of a global ProtocolType object.

So I run the program through valgrind, and two things happen: one, I get an enormous number of errors; far too many to pick through manually. Second, it gives me a different termination message. Valgrind craps out in only the second test case, with the output "pure virtual method called."

I'm fairly certain this has a different cause than my first error, since the ProtocolType class doesn't use any virtual methods, and is not a parent or child of any other class.

Is there a way to suppress the "pure virtual method called" exception, so that valgrind can reach the point where my bug occurs? Or can I generate a backtrace from valgrind's exception so I can resolve that?

2 Answers

You are thinking about this completely backwards. The error you see in release code is the victim of corruption that is occurring somewhere earlier. You cannot resolve the problem at the victim, you need to look at the perpetrator. So start going through those messages.

You are probably right that a lot of them are spurious. If so, you will quickly filter them down into categories. But it's even possible that there's some broken code you are calling an awful lot that happens to most often fail in a harmless way. For example, if you have a bug that accesses an array one byte out of bounds, if the array is usually 10 bytes, that's probably harmless because your allocator probably allocates 16 bytes. But if the array size is 16 bytes, ...

Start at the beginning. You don't want to be trying to troubleshoot a problem that occurs potentially long after the execution environment has already been corrupted.

Since these are unit tests, you can debug each unit test separately if you can run just that unit test. Then you know each test starts with a clean environment. But don't ignore any warnings or errors early in an execution run.

Generally Valgrind operates at a much lower level than C++ classes and object hierarchy. It does know how to recognize calls to new and delete and also C++ std::thread classes, but that is about all.

It looks like you have memory corruption. Just because you see a problem under gdb with ProtocolType doesn't mean the same class is causing the pure virtual call under Valgrind.

As @David Schwartz already said, start with the first error that Valgrind reports, fix that and repeat until there are no more. Quite often a small number of fixes will clear a large number of issues reported by Valgrind.

Related