Skip to main content
gamedev.net
🔒 Locked

Using assertions

Started by Turold Aug 6, 2007 at 2:28 PM 19 replies 2.3k views
Original Post
Turold
Turold
I'm building my first engine for my second game. 1. Should I make my own version of ASSERT macro of mayby do some of you use build in? 2. What do you assert? (My first guess: all kinds of pointers) Do you use assertions in release code?
Sneftel
Sneftel
Quote:
1. Should I make my own version of ASSERT macro of mayby do some of you use build in?
There's very little reason not to use the built-in macro.
Quote:
2. What do you assert?
Anything and everything possible.
Quote:
Do you use assertions in release code?
No.
Turold
Turold
Why don't u use assert in release code? Speed? What else?
fpsgamer
fpsgamer
Quote:
Original post by Terefere
Do you use assertions in release code?


No. In fact in a release build assertions are replaced by white space for you. That is to say assertions don't exist in release builds, only debug builds.

Assertions are simply for testing. When an assertion is triggered in a debug build, you should take steps to ensure your application cannot reach that sate again.

Assertions say that: "If I am triggered the program state has been invalidated."
Sneftel
Sneftel
Quote:
Original post by Terefere
Why don't u use assert in release code? Speed? What else?

Two reasons.

1. Speed. Assertions should not be limited by what can be computed efficiently.
2. Robustness. Write your code to work under a wide variety of strange circumstances, and write your assertions to complain about these circumstances. Bugs should be as loud as possible in debug mode, and as quiet as possible in release mode.
Turold
Turold
Yeah, but in a complex program you just can't test every single case. That's why u use assertions, since you assume that something UNEXPECTED may happen. You just can't test everthing.

Paulius Maruska
Paulius Maruska
Quote:
Original post by Terefere
1. Should I make my own version of ASSERT macro of mayby do some of you use build in?

Personally, I don't use the built-in assert macro, because I really hate how it reports failed assertion. Pop-up dialog isn't something I want. I have my own assert macro which is a lot more debugger-friendly

Quote:
Original post by Terefere
2. What do you assert? (My first guess: all kinds of pointers)

Actually, I almost never assert on pointers. If I use a pointer, then I know that it can be NULL. If I'm in a situation, when pointer can not be NULL - I drop the pointer and use reference instead.
Most of the time, I use assert to ensure that function was called with valid argument values.

Quote:
Original post by Terefere
Do you use assertions in release code?

No.

Quote:
Original post by Terefere
Why don't u use assert in release code? Speed? What else?

I treat asserts as a development tool (just like unit testing framework or leak-detecting memory manager). It's not meant to be used in release builds.

Note: I have defined two macros - ensure and assert. The ensure macro is the same as assert macro, except that it doesn't go away in release builds. However, I never use that macro. I just like to have it just in case.
fpsgamer
fpsgamer
Quote:
Original post by Terefere
Why don't u use assert in release code? Speed? What else?


We remove assertions mainly because of speed.

We can remove them in the release build because we did such a good job testing that no more assertions can be triggered.

However that is rarely true, but we remove the assertions anyways. This is because there is this idea is software engineering (whether good or bad) that even if the application enters a invalid state, we want the program to try to keep running anyways and hope that everything goes okay.

Some people feel this is better than unceremoniously terminating the application like an assertion would do.

Quote:
Original post by Terefere
What do you assert?


You assert anything and everything that should never happen.

For example if you know that if having a particular variable i, greater than or equal to 5 will result in undefined behavior then write:

assert(i < 5);

If that is ever untrue, your program will terminate immediately and you will be informed of the line number and file this occurred on so you can fix it.
Sneftel
Sneftel
Quote:
Original post by Terefere
Yeah, but in a complex program you just can't test every single case. That's why u use assertions, since you assume that something UNEXPECTED may happen. You just can't test everthing.

No, the inability to test everything has nothing to do with the use of assertions. After all, if you can't test everything, you can't assert everything either. The purpose of assertions is onefold: To detect bugs as early and as locally as possible.
CodeMunkie
CodeMunkie
The ASSERT macro will be removed from your code by the preprocessor in a Release mode, so feel free to use it.

Quote:
2. What do you assert?


The point of an assert is to provide communication to the user of a function. You generally use asserts at key points of the function (such as entry point and exit point) to ensure that certain conditions are true. It is not just a fancy way to test for NULL pointers. You may have heard about the concept of pre-conditions and post-conditions. In order to use a function correctly you need to understand what are the allowed range of values for parameters and what are the effects of calling the function. You can use assert to both document and enforce these conditions. For example, consider this function:

int divide(int dividend, int divisor)
{
ASSERT(divisor!=0);
return dividend/divisor;
}

In this case we always want a non 0 divisor, otherwise we have a divide by zero problem. Other uses are to make sure array indices are in the correct bounds, return values for functions are in some expected range, and yes, that pointers are not NULL (or maybe that they are in some cases). The key point is that the asserts should provide meaningful information about how the function should be used and how it should behave.
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
Turold
Turold
Some informative replies here, thx :)
Driv3MeFar
Driv3MeFar
I use the standard assert macro for debug builds and my own rassert macro for release-mode assertions (that basically just causes an _int 3). The rassert is used to debug a problem I'm seeing in release mode only. I like to keep different "release" and "retail" builds, the only difference between the two being the presence of rasserts in the former, but not the latter (so no assertions make it into the final build).
Evil Steve
Evil Steve
I use my own assert macro because the assert() macro doesn't play nicely with multiple threads. My own assert() logs the error, suspends all threads in the app apart from the current thread, shows a dialog box, then resumes all threads that were suspended.
Although normally when you hit an assert, you don't want to carry on, since something unexpected has already happened.
mrcheesewheel
mrcheesewheel
In numerous books I've read, assertions (whether they be the built in varients or custom made ones) are intended to document internal assumptions in the code. This means that they can check for internal self consistency in your codes implementation. Your code necessarily passes a 5 element array? assert it! You will never receive a NULL pointer? assert it! The sky *has* to be up? assert it! Basically you use asserts to ensure that implicit pre conditions are in place so that the method's actions can maintain it's appropriate class invariance guarantees. Pre conditions that are explicit should also be checked, but such checks should usually be done with a different mechanism. Another advantage of using assertions like this... is that if someone later takes your code to modify/extend, your assertions document the internal assumptions that the class makes.

In short: Assert things that you *know* should always be true. When you do not know, then check in another way. For an exceptional occurance... throw an exception.

Hope this helps,

Dan
David Neubelt
David Neubelt
Quote:
Original post by Sneftel
Quote:
1. Should I make my own version of ASSERT macro of mayby do some of you use build in?
There's very little reason not to use the built-in macro.


I think there are a lot of good reasons to write your own ASSERT macro.

1) You control what libraries it links in
2) You can add a lot more context information to asserts
3) Stack traces can be produced
4) Custom versions of asserts for designers, artists, programmers, code and data can be created.
5) You can add the ability to ignore all assertions of a type.
6) You can add custom rendering in game instead of a message box.
7) You can make it a lot more light weight
8) You can make it work on multiple platforms and guarentee the behavior is the same

I think when building an engine the first thing you should do is replace the standard assert.


Graphics Programmer - Ready At Dawn Studios
ToohrVyk
ToohrVyk
Quote:
Original post by David Neubelt
I think when building an engine the first thing you should do is replace the standard assert.


Though I agree with your other points, this is in my opinion incorrect. If your assertion mechanism (not talking about unit tests here) implies more than simply assert(condition); to use, you have a problem. And if it doesn't, then you can wait to implement your own until you actually need it, and use the default one until that time comes.

In short: YAGNI.
David Neubelt
David Neubelt
Quote:
Original post by ToohrVyk
Quote:
Original post by David Neubelt
I think when building an engine the first thing you should do is replace the standard assert.


Though I agree with your other points, this is in my opinion incorrect. If your assertion mechanism (not talking about unit tests here) implies more than simply assert(condition); to use, you have a problem. And if it doesn't, then you can wait to implement your own until you actually need it, and use the default one until that time comes.

In short: YAGNI.


I like that principle but I feel that a strong set of utilities for projects are invaluable. This is all from personal experience so depending on the project and team it may not be as important. However, I feel that debugging facilities from the start improve iteration and production time.

For example, debug rendering, an in-game debug menu, customized visual assertions, introspecting actors at runtime (their state and variables visually), and strong memory tracking tools will make a project much more stable and iteration times a lot quicker. This is just from my personal experience and these debug facilities have helped our team tremendously. Having artists being able to see asserts customized for them will keep them from bothering us programmers. Having designers able to view actors and tweak their values improve their iteration time and also stop them from bugging the programmers. Having used these utilities I couldn’t ever think of starting a project again without them as it has just helped us out so much. I think that’s why I made that statement.

Though, this is just personal experience and perhaps you’re right -- if you feel you don’t need it then don’t write it.

Graphics Programmer - Ready At Dawn Studios
RobTheBloke
RobTheBloke
Quote:
Original post by ToohrVyk
Though I agree with your other points, this is in my opinion incorrect. If your assertion mechanism (not talking about unit tests here) implies more than simply assert(condition); to use, you have a problem.


Please elaborate? I can't imagine using simple assert() on a large scale project, I just can't imagine it being all that useful. (I work with 40 full time C++ devs....). If some new component is being introduced into the app by another team and it happens to fire some asserts during the first few days of merging; do i really want it to work like a standard assert? or do i want to have the option to unload the offending module so I can carry on with my work? Having a robust debugging framework suited to your project needs *before* you start writing code is absolutely essential imho. Some of the tools we use could be called overkill for a small project, but they would still prove to be useful every so often....
Turold
Turold
Hmm, so for a very small project default assert is ok, while for a big project rolling a custom solution is the way to go.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.