Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Where to start when my application crashes at random places?

I'm developing a game and when I do a specific action in the game, it crashes. So I went debugging and I saw my application crashed at simple C++ statements like if, return, ... Each time when I re-run, it crashes randomly at one of 3 lines and it never succeeds.

line 1:

if (dynamic) { ... } // dynamic is a bool member of my class

line 2:

return m_Fixture; // a line of the Box2D physical engine. m_Fixture is a pointer.

line 3:

return m_Density; // The body of a simple getter for an integer.

I get no errors from the app nor the OS...

Are there hints, tips or tricks to debug more efficient and get known what is going on?

That's why I love Java...

Thanks

like image 267
Martijn Courteaux Avatar asked Jul 07 '10 18:07

Martijn Courteaux


2 Answers

Random crashes like this are usually caused by stack corruption, since these are branching instructions and thus are sensitive to the condition of the stack. These are somewhat hard to track down, but you should run valgrind and examine the call stack on each crash to try and identify common functions that might be the root cause of the error.

like image 71
Adam Shiemke Avatar answered Nov 15 '22 08:11

Adam Shiemke


Are there hints, tips or tricks to debug more efficient and get known what is going on?

  1. Run game in debugger, on the point of crash, check values of all arguments. Either using visual studio watch window or using gdb. Using "call stack" check parent routines, try to think what could go wrong.
  2. In suspicious(potentially related to crash) routines, consider dumping all arguments to stderr (if you're using libsdl or on *nixlike systems), or write a logfile, or send dupilcates of all error messages using (on Windows) OutputDebugString. This will make them visible in "output" window in visual studio or debugger. You can also write "traces" (log("function %s was called", __FUNCTION__))
  3. If you can't debug immediately, produce core dumps on crash. On windows it can be done using MiniDumpWriteDump, on linux it is set somewhere in configuration variables. core dumps can be handled by debugger. I'm not sure if VS express can deal with them on Windows, but you still can debug them using WinDBG.
  4. if crash happens within class, check *this argument. It could be invalid or zero.
  5. If the bug is truly evil (elusive stack corruption in multithreaded app that leads to delayed crash), write custom memory manager, that will override new/delete, provide alternative to malloc(if your app for some reason uses it, which may be possible), AND that locks all unused memory memory using VirtualProtect (windows) or OS-specific alternative. In this case all potentially dangerous operation will crash app instantly, which will allow you to debug the problem (if you have Just-In-Time debugger) and instantly find dangerous routine. I prefer such "custom memory manager" to boundschecker and such - since in my experience it was more useful. As an alternative you could try to use valgrind, which is available on linux only. Note, that if your app very frequently allocates memory, you'll need a large amount of RAM in order to be able to lock every unused memory block (because in order to be locked, block should be PAGE_SIZE bytes big).
  6. In areas where you need sanity check either use ASSERT, or (IMO better solution) write a routine that will crash the application (by throwing an std::exception with a meaningful message) if some condition isn't met.
  7. If you've identified a problematic routine, walk through it using debugger's step into/step over. Watch the arguments.
  8. If you've identified a problematic routine, but can't directly debug it for whatever reason, after every statement within that routine, dump all variables into stderr or logfile (fprintf or iostreams - your choice). Then analyze outputs and think how it could have happened. Make sure to flush logfile after every write, or you might miss the data right before the crash.

In general you should be happy that app crashes somewhere. Crash means a bug you can quickly find using debugger and exterminate. Bugs that don't crash the program are much more difficult (example of truly complex bug: given 100000 values of input, after few hundreds of manipulations with values, among thousands of outputs, app produces 1 absolutely incorrect result, which shouldn't have happened at all)

That's why I love Java...

Excuse me, if you can't deal with language, it is entirely your fault. If you can't handle the tool, either pick another one or improve your skill. It is possible to make game in java, by the way.

like image 20
SigTerm Avatar answered Nov 15 '22 07:11

SigTerm