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

I develop a game, and when I do a specific action in the game, it crashes. So I went debugging, and I saw that my application crashed into simple C ++ operators, such as if , return , ... Each time I run it again, it accidentally crashes on one of three lines, and this never will succeed.

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 do not get any errors from the application or OS ...

Are there tips, tricks, or tricks to debug more efficient ones and find out what's going on?

That is why I love Java ...

thanks

+6
c ++ debugging crash
source share
15 answers

Accidental failures like this are usually caused by stack corruption, as they are branch instructions and are thus sensitive to the state of the stack. They are difficult to track, but you have to run valgrind and examine the call stack at each failure to try to identify common functions that may be the main cause of the error.

+10
source share

This is mainly due to stack corruption, but heap corruption can also affect programs in this way.

Damage to the stack occurs most of the time due to "shutdown by one error."
damage to the heap is due to the fact that new / delete is not handled carefully, for example, double deletion.

It basically happens that overflow / corruption overwrites an important instruction, and then much later, when you try to execute the instruction, it will work.

+5
source share

I like to take the second step back and think through the code, trying to catch any logical errors.

You can try to comment on different parts of the code and see if this affects how the program is compiled.

Besides these two things, you can try using a debugger like Visual Studio or Eclipse, etc.

Finally, you can try to post your code and the error you get on a website with a community that knows programming and can help you deal with the error (read: stackoverflow)

+4
source share

Are there tips, tricks, or tricks to debug more efficient ones and find out what's going on?

  • Run the game in the debugger, on the verge of failure, check the values ​​of all arguments. Either use the visual studio window or use gdb. Using the "call stack", check the parent procedures, try to think what might go wrong.
  • In suspicious (possibly crashed) procedures, consider dumping all arguments to stderr (if you use libsdl or on * nixlike systems) or write a log file or send duplicates of all error messages using (on Windows) OutputDebugString. This will make them visible in the "output" window in the visual studio or debugger. You can also write "traces" (log ("function% s was called", __FUNCTION__))
  • If you cannot debug immediately, create a crash dump kernel. In windows, this can be done using MiniDumpWriteDump, in linux it is set somewhere in the configuration variables. Kernel debugs can be handled by the debugger. I'm not sure VS express can handle them on Windows, but you can still debug them using WinDBG.
  • If the class crashes, check * this argument. This may be false or zero.
  • If the error is really evil (elusive stack corruption in a multi-threaded application that leads to a delay failure), write a user memory manager that will override the new / delete will provide an alternative to malloc (if your application uses it for some reason, it may be possible), AND, which blocks all unused memory using VirtualProtect (Windows) or an alternative for the OS. In this case, the entire potentially dangerous operation will instantly lead to the application crash, which will allow you to debug the problem (if you have a Just-In-Time debugger) and instantly find the dangerous routine. I prefer such a "user memory manager" for boundschecker, etc., since in my experience this was more useful. Alternatively, you can try using valgrind, which is available only for Linux. Please note: if your application allocates memory very often, you will need a large amount of RAM to be able to block each unused block of memory (because to block, the block must be large PAGE_SIZE bytes).
  • In areas where you need sanity checking, use ASSERT or (a more efficient IMO solution) write a procedure that will crash the application (by throwing std :: exception with a meaningful message) if any condition is not met.
  • If you have identified a problematic procedure, go through it using the debugger step in / step over. See the arguments.
  • If you have identified a problematic procedure, but cannot directly debug it for any reason, after each statement inside this procedure, dump all the variables in stderr or logfile (fprintf or iostreams is your choice). Then analyze the results and think about how this could happen. Be sure to clear the log file after each entry, or you can skip data right before the crash.

In general, you should be happy that the application will work somewhere. Crash means an error that you can quickly find with the debugger and exterminate. Errors that do not lead to a program crash are much more complicated (an example of a really complex error: given 100,000 input values, after several hundred manipulations with values, among thousands of outputs, the application produces 1 absolutely incorrect result, which should not have happened at all)

That is why I love Java ...

Sorry if you cannot learn the language, it is entirely your fault. If you can not cope with the tool, choose either another, or improve your skills. By the way, you can make a game in java.

+4
source share

Seg crashes / crashes usually occur when you access a memory location that it does not have access to, or when you try to access a memory location in a way that is not allowed (for example, trying to write to a read-only mode location).

There are many memory analyzer tools, for example, I use Valgrind, which is really good at talking about the problem (not only the line number, but also the reasons for the failure).

+3
source share

There are no simple instructions in C ++. If it is as simple as the condition you are evaluating. The return is as simple as the expression you return.

You must use a debugger and / or publish some of the failed code. It may not be very useful when “my application crashed” as information.

+2
source share

I had problems like before. I tried to update the GUI from different threads.

+1
source share

If the if are associated with dereference pointers, you will almost certainly corrupt the stack (this explains why the innocent return 0 fails ...)

This can happen, for example, by going out of bounds in the array (you should use std::vector !), Trying to strcpy contain the string char [] without end '\0' (you should use std::string !), Passing the wrong size memcpy (you should use copy-constructors!), etc.

Try to figure out a reliable way to play, then put the clock on the damaged pointer. Run the code in turn until you find the very line that corrupts the pointer.

+1
source share

Look at the disassembly. Almost any C / C ++ debugger will gladly show you the machine code and registers in which the program crashed. Registers include an instruction pointer (EIP or RIP on x86 / x64) where the program was stopped. Other registers usually have memory addresses or data. If the memory address is 0 or a bad pointer, your problem arises.

Then you just need to work back to find out how it happened. Hardware breakpoints when changing memory are very useful here.

On Linux / BSD / Mac, using GDB scripting functions can help here. You can script things so that after the breakpoint has hit 20 times, it allows the hardware clock to address the array element 17. Etc.

You can also write debugging to your program. Use the assert () function. Everywhere!

Use assert to check the arguments for each function. Use assert to check the status of each object before exiting a function. In the game, confirm that the player is on the map, that the player has health from 0 to 100, they say everything you can think of. For complex objects, write the verify () or validate () functions in the object itself, which checks everything about it and then calls them from assert ().

Another way to write to debugging is to use the program signal () on Linux or asm int 3 on Windows to exit the debugger from the program. You can then write the temporary code to the program to check if it is in iteration 1117321 of the main loop. This can be useful if the error always occurs in 1117322. The program will run much faster than using the debugger breakpoint.

+1
source share

some tips:
- run the application under the debugger, along with symbol files (PDB).
- How to install Visual Studio as the default post-mortem debugger?
- set default debugger for WinDbg Just-in-time debugging
- check memory allocation override new ones and delete and redefine malloc and free

+1
source share

Another trick: turn off code optimization and see if the breakpoints make more sense. Optimization allows you to swim small fragments of your code in unexpected places; a mapping that returns to source may be less perfect.

+1
source share

Check pointers. By assumption, you are dereferencing a null pointer.

0
source share

I found "random" crashes when there is a link to a remote object. Since the memory is not necessarily overwritten, in many cases you do not notice it, and the program works correctly, and then the crash after updating the memory is no longer valid.

ONLY TO DISABLE TARGETS, try to comment on some suspicious “deletions”. Then, if it no longer breaks, you are here.

0
source share

use the GNU debugger

0
source share

Refactoring

Scan all the code, make it clearer, if not clear, first read, try to understand what you wrote, and immediately fix what seems to be wrong.

You will certainly detect problems this way and fix other problems as well.

-one
source share

All Articles