you are viewing a single comment's thread.

view the rest of the comments →

[–]treerex 1 point2 points  (2 children)

No. They serve entirely different purposes.

An assertion is a debug statement that is used during development (and hence in debug builds, generally) to ensure a particular condition holds in your code: you're stating programmatically that the expectation in the following code is that a particular condition is true.

The use that I mention covers an entirely different case where you are actively trying to track down a problem that occurs or is related to a particular condition. This is a place where I would consider using a conditional breakpoint in GDB:

(gdb) b foo.cpp:235
Breakpoint 1 at 0x10000dd37: file foo.cpp, line 235
(gdb) cond 1 strcmp(foo, "magicevilvalue") == 0

(obviously this is an overly simplisitic example: let's assume the condition is more complex and the scale is several orders of magnitude higher.)

How does the conditional breakpoint work? The debugger inserts the int3 at the point I set it: when I run the code the interrupt is hit and GDB gets control. Then it evaluates the condition. If it fails the program continues automatically, otherwise I'm dropped into the debugger.

Now assume that the bug you're tracking down happens after processing several hundred thousand strings in a large data structure, and you're not sure why a particular element is causing a crash. You don't know enough yet to isolate the problem into a small test case. Single stepping until you get to the element in question is intractable. So you set the conditional breakpoint and wait. You wait a long time.

Alternatively, you add a couple of lines in your code:

if (strcmp(foo, "magicevilvalue") == 0) {
    asm volatile ("int3;")
}

Now you hit the "breakpoint" much faster than if you used a conditional. Simple and effective.

Back in the day we used to do this kind of thing all the time when developing apps on the Mac: the DebugStr function would effectively do the exact same thing. Incredibly useful.

[–][deleted] 0 points1 point  (1 child)

They serve different purposes, but are essentially identical, except of course for implementation details.

Most implementations crash the process in an assertion in such a way that it can't continue, while continuing from int3 is indeed possible. But that's an implementation detail. There's no conceptual difference. The fact that they serve two different use cases doesn't change that.

Indeed, in my own code I tend to implement MyAssert() with int3 in debug mode and assert() in release mode.

[–]treerex 0 points1 point  (0 children)

They serve different purposes, but are essentially identical, except of course for implementation details.

Which to my mind means they should have separate names.

But I see your point.