Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop when a condition in if statement is satisfied, when debugging

How to stop when a condition in if statement is satisfied, when debugging? For example:

if (!check()) {
  int a = 0;
}

The int a = 0; is dummy code and then I put a breakpoint there. If I put a breakpoint inside an empty if loop the debugger won't stop there, it only stops at instructions it can execute. Even if you do int a; just a declaration it won't stop.

Can I do this in other way rather than writing dummy code?

Thanks

like image 533
user2381422 Avatar asked Jul 10 '13 09:07

user2381422


People also ask

How do I stop a debugging session?

To end a debugging session in Microsoft Visual Studio, from the Debug menu, choose Stop Debugging.

What do you place down in order to stop at a line of code to Debug?

Step into code line by line To stop on each statement when you're debugging, use Debug > Step Into, or select F11. The debugger steps through code statements, not physical lines.

What is conditional breakpoint?

Conditional breakpoints allow you to break inside a code block when a defined expression evaluates to true. Conditional breakpoints highlight as orange instead of blue. Add a conditional breakpoint by right clicking a line number, selecting Add Conditional Breakpoint , and entering an expression.


1 Answers

Can I do this in other way rather than writing dummy code?

Yes!

In a debugger, you should be able to add a breakpoint and set it to only break when a specific condition is met. How to do this depends on your IDE, but in mine I can right-click on the breakpoint in the code editor gutter or in a separate Breakpoints window, and select Properties from the popup menu. Then I get this dialog:

Breakpoint properties dialog with Condition set

You can see that I've set the 'Condition' property, which will be evaluated every time the code hits that breakpoint - but the breakpoint will only break when the condition is true. Ie, if check() returns true when everything is ok, !check() will make it break when check() returns false.

This tends to slow down your program a bit if this method is called a lot, since typically to evaluate an expression like this the debugger has to (internally) break in and evaluate something. But it's neat functionality. Note all the other properties you can set as well, and that's not even getting to what the dialog looks like after clicking the Advanced button...

To answer your other questions:

If I put a breakpoint inside an empty if loop the debugger won't stop there, it only stops at instructions it can execute. Even if you do int a; just a declaration it won't stop.

If the if block (not loop) is empty, then there is nothing for it to stop on. It can only stop on actual code. int a; is just a variable declaration; for simple types, no code is actually generated for this. (It can be for more complex types, though, MyClass a; for example, since that would call the constructor.) Even if you write a bit more code:

if (!check()) {
  int a;
  a = 5;
  b = a;
}

your compiler might still not generate any code for this since it might figure out that the code never actually does anything. This depends to some extent on your optimisation settings, but some compilers will optimise it away even without any specific optimisation setting at all.

Sometimes it can be handy to break in code, rather than using the IDE, for various reasons (sometimes just the speed of condition evaluation.) In this situation, I tend to use a function call to break on, since the compiler doesn't know the function doesn't modify the state of the program and can't optimise it away:

if (!check()) {
  rand(); // <- breakpoint here
}

But typically making good use of your IDE and debugger features is a better approach.

Edit: since this is getting upvoted (thanks guys) I thought I'd add another approach, for completeness. A software / debugger breakpoint occurs with interrupt 3, which is patched in by the debugger. The int 3 assembly instruction is only one byte long, so can be patched over any other instruction; when the program breaks, the old instruction can be patched back in temporarily. But as well as the debugger putting this in on the fly, you can put it in in code.

In other words, you can force your program to break in code (and be caught by the debugger; if you're not running under the debugger this might cause problems; typically, your program will abort) by something like this. Syntax depends on your environment:

if (!check()) {
  __asm int 3
}

Or even better, avoiding environment-dependent code, many C++ compilers have intrinsics or macros, such as DebugBreak(); or __debugbreak which you can use like this:

if (!check()) {
  DebugBreak();
}

When you run your program under the debugger you will find that execution breaks on that line.

There's little reason to use this normally. One I've seen is a custom assert handler which breaks into the debugger when the assertion fails, but allows execution to continue afterwards.

like image 183
David Avatar answered Oct 06 '22 03:10

David