Do Programmers Actually Use Assertions?
P.Chalin queries: "Do programmers actually use assertions (like the assert statement of various programming languages)? If so, what should be done when errors or exceptions are raised during the evaluation of an assertion? I am collecting opinions and stats via a short questionnaire. Thanks."
Yes, but I usualy define my own assert.
and to avoid putting my email in a survey, I use debugging messages as needed while debugging. If it's a web site, I'll also have it catch and forward them to my email. I don't really use assertions except that I write a lot of code to deal with unusual input in a non-fatal fashion. I was an on error resume next sort of guy back in the VB days.
My philosophy has been that unless security issues are involved, failing on an error is not much better than not checking for an error at all, if the program crashes in both instances, as happens when you use an assert(). Ideally, either errors are handled in the least-fatal manner possible, or you develop the right abstractions to enable you to write error-free code.
I only use assertions in unit test code such as here and here.
I use them like crazy when I write 'test drivers' for functional units of code (albeit Object Oriented classes etc).
I write programs for algebra (in Maple). I never use assertions. The programs must work correctly for all valid input. Invalid input is caught with a type check, and an appropriate error is returned. Assertion failures can only frustrate users, who typically do not understand what is going wrong.
In Soviet America the banks rob you!
Design-by-contract is tha shiznit. It keeps your code base quite stable.
Assertions (usually) are a preversion of the failfast principle, because they can be turned off. For the same reason you can't fit a 120v plug in a 240v outlet, error checking in software should be a permanent and reliable function of the design of the system.
Either your software is broken, or it isn't. If it is, you (and the users) need to know about it as soon as possible to prevent little errors from causing big errors.
Now, if you want to have an assertion that cannot be disabled, and is basically just syntax sugar for if(condition) throw new SomeException();, that could be useful. But exceptions that can be disabled only lead to a false sense of security.
I'm working on some old library code for my job now and it's chock full of assertions. I think it's rediculous that a library call should cause the calling application to exit because of a failed assertion. In a "normal" application, assertions don't belong outside of main().
-73, de n1ywb
www.n1ywb.com
Assuming that assertions are used only for the "debug" version of the program, they are ideal for code that needs to be as fast as possible but can still work if there are slowdowns, such as device drivers. They're great for parameter checking during development. Once the code has been verified to work, they can be automatically compiled-out for the "release" version of the program.
And the men who hold high places must be the ones who start
To mold a new reality... closer to the heart
Real programmers do not use them. Code works fine the first time. You have "bugs" in your code???
"Who are in control, they are not in control of anything - they don't even control themselves!" - Glen Beck
I read the Eiffel book, but I've never been in a position to actually write code in it. But I love the concept of programming by contract.
I just use assertions to do preconditions, postconditions, and checks. Invariants are a nice idea, but in practice seem to be a big performance hit. I just do invariant-like assertions as needed.
I assert the heck out of my code. You can see some of it here.
I don't see too many assertions in other people's code. Then again, I don't see too much that looks like planning or insight in other people's code most of the time, so why should I be surprised. I can't believe how sloppy we are as a profession. Like my coffee cup says...if builders build buildings the way programmers write programs, then the first woodpeckers that came along would destroy civilization.
"Once we've identified and embraced our sickness, we'll have strength...and that's when we get dangerous." - John Waters
At my place of employment we use Asserts liberally but with an emphasis on using them properly. Specifically, asserts are not a substitute for appropriate error handling. An assert should be used only as a mechanism for bringing developer or tester attention to a special case or flaw and making it convenient to debug (by providing a change to break in). Subsequent error handling should still follow. Another way to look at this is that asserts should always be ignorable (the product doesn't crash, corrupt data, or enter an unrecoverable state if the assert is ignored).
Moderator hint: a comment is neither "Flamebait" nor "Troll" if it is true.
Session Timeout
Your session has timed out. Please register again.
Perhaps posting to slashdot wasn't the best way to collect data, but it will give them something to think about with regards to server application reliability.
-Hope
Years ago I programed on a Fairchild electronic circuirt bord test machine in the origional Dartsmith BASIC the forced me to use the let syntax.
Does this count?
zenray
Quite a bit actually; if I'm starting a new project one of the first things I do is add a few simple assert-like macros that use the appropriate error-reporting infrastructure.
:-).
I find that they can help quite a bit to catch less obvious bugs.
If I'm adding code to an existing large project though, I tend to follow whatever the general convention of that project is (i.e., I don't add my own assert macros
[I was gonna fill in your survey too, but I'm not at work, so I can't reply to the email check...]
We live, as we dream -- alone....
...when I sit and code too long.
Assuming that assertions are used only for the "debug" version of the program, they are ideal for code that needs to be as fast as possible but can still work if there are slowdowns, such as device drivers. They're great for parameter checking during development. Once the code has been verified to work, they can be automatically compiled-out for the "release" version of the program.
They can indeed be usefull during development for the person who is writing the code. After development they should be removed, not just compiled out. I have seen too many cases where assertions are used for primitive exception handling which is a terrible way of programming.
If such an assertion is triggered, you mostly have no means to discover why it has triigers, which make debugging such problems a pain. I had to do that a few times and it is not fun if the program consist of about half a million lines of code.
What a joy if you have to maintain code written by someone who does not know how to program.
Yes and in fact if you look into GCC there is more checking code than most people think because most of the time in a released compiler these checks are not enabled. (--disable-checking). In fact in some cases even on the main development some checking is not enabled by default because it just take so long (like 5 days) to just bootstrap the compiler. I am taking about gcac checking. Also RTL checking takes a long time too.
l ag ,rtl,tree is fun as it takes 5 days to build a compiler even on a fast computer.
--enable-checking=assert,fold,gc,gcac,misc,rtlf
Tom Yager of InfoWorld had an article that spoke to this issue, a few weeks ago. He was talking about how most OSes fail to guard applications against timeouts and hardware failures. They leave it up to application developers to bloat their code will all kinds of handlers. Most applications simply die when faced with these kinds of problems. It would take far too long to code for all the possibilities, and cost too much.
Their site requires cookies for state management. I had them turned off for all but specific sites. Perhaps an assert(cookie_is_valid) would be in order before that session lookup.
-Hope
As your software environment and processing power shrink (think game consoles, PDAs, cell phones...or simply low-level code that can't afford the bloat), you have to make assumptions. It's no longer realistic to believe that every code module should handle every set of states and inputs like a perfect black box.
As you increase the lifespan of the code and the number of coders working with it, the usefulness of asserts also increases. When you write your brilliant, super-fast method that only works on normalized floats or ints with 22 significant bits, you'll know the calling code is following your rules... but in 6 months when the function becomes more popular without your knowledge, you're going to want it to blow up the moment it's misused.
There are two kinds of error checking, one for debugging and one for using the final product.
Relying on assert() for a final product is not helpful for the user, the user does not generally have a method to fix and rebuild the product even if the user knows the line and file that found the error. For the developer the assert() is very useful to find places where bad conditions exist.
The end user needs a more sophisticated error checking that visibly explains what is wrong, or simply ignores creating a spheres that have a 0 or negative radius for example (or simply makes sure the sphere radius is nonzero and positive).
I write very large applications that have a huge customer base. Null Pointer exceptions or the like are totally unacceptable errors for the user to see.
Assertions allows the developers of large and complex applications to support their code over the long run which is always the biggest flaw of most large applications.
It is always better to have a slower application verbose application that a fast and silent one. Example:
--} IE - Overly optimized for performance improvements and pretty much impossible to debug complex JavaScript with.
--} Mozilla - Well written and fantastic to debug complex JavaScript with.
Obviously simple, small, run a few time applications should not need assertions.
JsD
I use assertions to document assumptions in the code. Just occasionally they are useful for debugging. I tend to keep them enabled anyway otherwise they get out of date (referring to variables that no longer exist etc.)
Is Betteridge's Law of Headlines Correct?
I am collecting opinions and stats via a short questionnaire. Thanks.
No...no this is not right at all. I already got tricked into giving out my personal info in exchange for a candy bar...no more surveys for me.
Wait, are there movie passes being given away?
I checked out a copy of shipping code and asserted it all over, including some asserts that other developers said "now you are just being silly, how can this assert not be true". Within hours we found tons of dormant bugs all over the place and two of the "silly" asserts were triggered.
Our bug count list went down by 50% within a week of asserting the code, and later on, in several occasions when some customers reported bugs all we had to do was run the instrumented, asserted version and the asserts caught the bug at once.
Many people use assert() like an exception, and they're not made for that.
You should use assert() to check for situations when the condition should never be false, unless there's a serious flaw in the software logic.
For example, assert(malloc() != NULL) is bad, but something like this is ok:
if(list->head != NULL) {
void* last = get_last_element_of_list(list);
assert(last != NULL);
}
If assert fails, I abort().
I use assert to detect the problem instead of detecting its byproducts.
--
Go Debian!
- Assertions are for notifying you that something occurred during debugging/testing that should be impossible. This could be notifications of bad data that's slipped past validation. Note that assertions are stripped out of release builds.
- Exceptions are errors that cannot be ignored. For example, failing to open a file before reading it.
- Error returns are errors that occur that are not a big deal to ignore. This could be parsing an empty or invalid string.
For example, you might have a constructor that allocates space for a private pointer and a function (call it SetIt) that copies data to it.
In this case, the constructor would throw an Exception if new[] fails. This is an error that cannot be avoided.
SetIt should assert if the private pointer is invalid. It could also assert if the incoming data is NULL, which should alert you that there's a way to send in invalid pointers.
SetIt can then return an error if the incoming data (user typed I assume) is too long or incorrect format.
Oz
...when "assumptions" will do? ;-)
"Play is the only way the highest intelligence of humankind can unfold." -- Joseph Chilton Pearce
That's a totally baseless asser...
Oh. Nevermind.
Did anyone else notice you can take it multiple times?
Moderator hint: a comment is neither "Flamebait" nor "Troll" if it is true.
grep -R assert /usr/src/linux-2.6.10 | wc -l
2490
Unless of course you're convinced you can write perfect bug-free code.. Am I the only one that thinks this is too obvious of a question to constitute an "Ask Slashdot" ?
oh well
I did use asserts in the past, several times in fact. I am not sure the occassions, but I think they were all programming related. About four or five times.
HTH.
I use C++. I don't literally use "assert" (which is a macro, not a statement in C++), beause in C++ it is throw-away code. It stops working once NDEBUG is undefined. Someone wrote that turning off checks in production code is like unbuckling your seatbelt when you leave the driveway. I read that, and believed it. So much for assert.
I do use "throw", which isn't a statement either (it's an expression). Using throw leads to the question "what does the catch do?" Simple rule: If a catch can't fix an program, or at least make it less severe, don't code the catch. Let the exception propagate.
It helps to establish an exception hierarchy. I don't particuarly like the C++ library version, but at least it is "standard."
Assertions allow the programmer to do checking for conditions that would indicate a bug in the code, in an attempt to identify the problem sooner, as the sooner you see the problem, the easier it is to find and fix.
Having assertions only exist in debug code is also an important principle, that actually allows them to be more useful. For example, if I have some very low-level routine that is time critical, I am not going to want to do parameter validation in the low level routine, particularly if bad parameters are reflective of a bug in the calling code.
The assert allows me to do robust checking for programmer-errors, while not screwing up the performance of the released product. For example, in an object ref-counting scheme, I have asserts all over the place in the low-level ref-counting mechanisms to ensure that nobody tries to do something like add-ref the object once it's destruction sequence has started, and various other programmer-errors.
I don't want these sort of checks in the release code. Another example -- I want the C-Runtime library in debug mode to validate all the parameters that I pass it as best as it can, but I would be REALLY pissed if it were doing those checks in release mode, since it would effectively slow down code of mine that is known to be bug-free.
As a general rule, asserts should be used to identify conditions that in theory can't exist, or that indicate an error on the part of the caller.
Yes, of course. Almost all functions should have at least one assert (ErrFatalDisplayIf in PalmOS) in the debug build, IMO. I generally add sanity checks as well - if I know an integer argument should never be much above 200, assert that it's not.
Hell, no way.
Assertions are for internal self-checking. Code like checking that a pointer isn't NULL can't be turned into a useful error message for an user. At best, it comes out as "Internal error in module foo", which isn't really helpful to anybody. You could remove it, but that's even worse, now the application will just continue and crash at some random point.
Error checking should ideally be done in layers. By that I mean that the DrawSphere function, Sphere class or whatever should either FAIL HORRIBLY the moment you try to use a negative radius, or do nothing and return an error to the caller, but definitely NOT pretend that everything is going fine. That's a sure recipe for getting some really strange bugs. The user interface should prevent that from ever happening anyway.
Now, why? Because checks in the lower levels like the drawing function are there to make sure everything works as intended. If a negative radius somehow got passed it means that the UI is bad, or the caller did something wrong. Once at the lowest level you've determined that something is wrong, very often the only sensible option is a fatal abort.
The sphere drawing code doesn't know what it's drawing, and what are the consequences of stuff not drawing as it should. The application's UI is a lot more qualified to control these things, and that's where it should be done.
That is indeed common practice, and the traditional use of assertions. Whether it's the best practice is a different question.
In recent years, there has been a general acknowledgement within the software development community, and indeed among end users, that bugs happen. It's simply the nature of the beast. In most fields (excluding those where bugs simply aren't allowed, ever, and vastly higher investment is made in quality control) what's more important is that the application handles the situation gracefully when a bug does occur, and that when a bug is found, it is swiftly and effectively fixed.
Now, obviously you don't normally want your end users seeing the intimate details of your code, but the idea of having run-time sanity checks for internal errors even in release code isn't absurd by any means. After all, as an end-user, wouldn't you far rather your e-mail client noticed early that something wasn't quite right and shut down relatively cleanly, potentially allowing you to back up your data and/or obtain a tool to recover it before the problem went too far? The alternative -- continuing as if nothing's wrong, but based on some bad data -- could easily lead to more serious corruption and permanent data loss, with a bug report only getting filed when it's too late to do anything about it.
Of course, using assertions heavily can incur a significant performance hit, which may or may not be acceptable in your particular application. However, I would argue that the basic idea of assertions is just as valid in production code, and perhaps it's better to leave at least a key subset of assertions in your finished product, with handlers that shut down cleanly and ask the user to pass on certain key information to the developers in order to fix the bug.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
If so, what should be done when errors or exceptions are raised during the evaluation of an assertion?
Scream and throw up. Or in other words, loudly dump core. That's what the asserts are for.
Asserts should always be turned off in production software, so it doesn't matter how noisy the asserts are. If you're an open source project and are worried about 1&m3r distros building your stuff with debug on (I've had it happen to me), then turn it off by default.
Don't blame me, I didn't vote for either of them!
How do assert "should never be much above 200" in C/C++? I guess you could use assert(!(x>200+MUCH)) but how much is MUCH?
Doesn't it make you feel good to know that our freedoms are protected by politicans, lawyers and journalists.
You could remove it, but that's even worse, now the application will just continue and crash at some random point.
Or not. A lot of times, things that are asserted just don't cause a problem later on. Especially if the rest of the code is fairly well written and free of lots of intermodule dependencies. Why have a probability of crashing at 1.0, when you can have one that is less than 1.0? Yes data corruption is an issue, but again, see the comment above about intermodule dependencies. Good code checks assumptions at multiple levels and gracefully recovers.
Once at the lowest level you've determined that something is wrong, very often the only sensible option is a fatal abort.
Completely wrong. A crash simply isn't the only thing to do. And in many cases, it can be a very bad thing. Sure, if a user-interactive program crashes, then the user restarts the program, no big deal. But if your code is running on Mars, then it sure is a big deal. And don't try to tell me that that is an extreme situation, that kind of thing happens all the time in embedded programming.
Mad Software: Rantings on Developing So
Code like checking that a pointer isn't NULL can't be turned into a useful error message for an user.
Assertions aren't for things that can happen. You don't use an assert to check user input, for example. That said, unless you're in some really performance critical code, it's often best to include an assertion and standard error checking. So if you're coding up malloc(), and you get a null pointer somewhere that you're never supposed to get it, if you're in debug mode, you panic, but if you're not in debug mode, maybe you return NULL instead.
Once at the lowest level you've determined that something is wrong, very often the only sensible option is a fatal abort.
Depends how highly available your program needs to be. If it's just an instance of GIMP, maybe it's OK to dump core and exit (even then I'm skeptical, though, it's probably better to give the user the choice whether to abort, retry, or fail).
Another consideration is security, though. If you can't confine the error to a single part of the program and reboot that part, and the program deals with anything security-sensitive, it's probably best to just shut down. Depending just how security-sensitive the program is, you might not even want to come back up until there's manual intervention.
But I can't stress how useful they are in debugging your code, as long as they are only active in DEBUG mode!
I have asserts in every single exception in every piece of code. It makes debugging through that weird unicode input a decisive task, rather than looking at your code thinking... "Well it could be...".
You mentioned that assertions are valuable in large applications, but then you talk about IE vs. Mozilla and debugging JavaScript -- that's not assertions at all; that's error-handling.
Any browser takes HTML, JavaScript, CSS, etc. as user input -- as such, it could be *anything*, and the application must parse it safely. Handling errors in this input should never involve assertions, though, and assertions should always be turned off before distribution, because they are by definition a very unpleasant way to handle errors.
If you're taking a "design by contract" approach, you basically define the "contract" for each method with your assertions. If there's no sensible value your method foo() can return if the argument is null, you make that part of the "contract" with code that calls method foo(). When another programmer screws up and passes in null, it's instantly obvious to both of you who made the mistake, and how to fix it.
Without the contract (which ideally will be automatically documented), the other programmer has to guess what will happen if he passes in null. Suppose you just return a -1, or 0, or null result when foo() gets useless input. The program will keep working -- but that's very bad, because it could hide a serious bug (which might go out in the release), and make it very difficult to track down later.
Assertions make violating a method contract a fatal error -- which can often not only make it easier to avoid bugs, but when they do happen they are usually noticed so quickly that the offending code won't even get checked in.
I would consider it a mistake to assert that memory allocation was successful; that's the kind of thing that has to be handled by code, not an assertion. But you might assert that a pointer is non-null if you require it to be initialized.
In other words, an assertion should explain assumptions and how things work to someone reading the program. Generally, these are not dynamic conditions because those need to be handled in other ways.
void assert() { return; }
if
Assert() is a big assest to program maintanence and debugging.
Bad uses of assert() are like bad comments: they do nothing to help you. Good uses of assert() serve two purposes: (1) to document assumptions made by the code, and invariants that must be maintained, and (2) to make debugging easier when and assumption/invariant is violated.
When reading code, you know there are probably some corner cases that don't work correctly. There are going to be assumptions embedded in the code. Future maintainers of the code need to know these assumptions; they can either find it by violating them and then tripping over the resulting bugs, or else by reading comments.
is as readable as a
to the same effect, except that the assert() statments are machine-checkable.Assert() follows the principle of "fail fast": when something goes wrong, you want the program to stop right away, before it starts corrupting things. When you get a backtrace at (or soon after) the problem occurred, it is much easier to track down what's gone wrong, than if the program crashes from a null pointer exception a few million instructions later. Or worse, the corrupt data might not be noticed for a long time; at that point you can all you know is that _some_ piece of code corrupted data. An assert() can significantly narrow the search for the offending line(s).
This is the way to do it -- abstract out the error-testing code (assertions and all that) and use unit tests enough to catch the assert-style bugs before the software hits a user's desktop, not after. Remember, YOU know what to do with an "assert failed" message. The user doesn't have a clue.
Don't thank God, thank a doctor!
I never use assert, and all the apps I've written work perfectly. I'm even posting this using one of my assert-free apps, and guess wha#@#$^@!#%#$%@#$NO CARRIER
"The newly born animals are then whisked off for a quick run through a giant baking oven." --heard on Food Network
"But I can't stress how useful they are in debugging your code, as long as they are only active in DEBUG mode!"
That is fine as long as you don't have artists choosing to run the non-debug build because they don't like the build 'crashing' when they test their stuff....
Whatever's sensible, I guess. In my Free software work (PalmOS text editor) I use a lot of unsigned 16-bit integer values, for example, so if the number of characters that fit across the screen becomes 65,000, then I've probably done something like "x=3-5" and overflowed x.
Assertions are simply not for cases where graceful recovery is easy. For instance, suppose an assertion in code that implements a doubly linked list trips because of some impossible state, like having a list where the first item is NULL, but the last isn't.
Well, what exactly do you do about a linked list where there is an end but no beginning? That kind of thing either indicates a serious error in the logic or memory corruption. Either way, graceful recovery is next to impossible.
Now, if this is happening on Mars I'm sure there are safeguards. Perhaps the assertion makes the whole thing reboot. Of course, I'm sure that on Mars they have some very fancy error handling, but I'm still sure that at some point the program just decides that things are too screwed up to continue and reboots.
I don't think you can assert that.
Once at the lowest level you've determined that something is wrong, very often the only sensible option is a fatal abort.
Surely it's better to throw an exception (or even an error code)? If nothing else catches it then the main function should, at which point it's trivial to end the program. It also means information can be passed from a low level to a higher level where it's more likely an informative error message can be generated. It also means that objects have a chance to destroy themselves. This is important if you've allocated resources that won't be freed by the platform when your program aborts. Should destructors abort? Not sure about this one. I've always allowed the destructor to finish but logged the error. As a general rule I try to keep destructors very simple.
I wouldn't use assert(). There are plenty of better alternatives.
Who ordered that?
First, a lot of apps should refuse service when an assertion fails, because they may be promising or reporting false success. You may think you'll catch more flak for a halt and an identified bug than for mysterious ongoing anomolies, and you may be right. But you may end up being publicly flogged if your program pretends to work for three days when it's actually just throwing away data.
Second, you can make assertions do whatever you want. Most languages have some basic assert functionality built in, but having a brain-dead assert available is no excuse for not writing your own. You can have it log, send email, terminate, launch missiles, or whatever, based on compile flags/application preferences/day of the week/time of the month.
And performance hits? Please. Use a profiler. I'm sure that some assertions in some apps should be turned off. Personally, I've never had to do it. If I ever do, you can be sure that my code will have two kinds of assertions, the performance killers that I compile out and the other 95%.
I work on kernel device drivers. Some functions assume that they are called with a lock held. Having an assert at the begining of this block of code adds a guarantee - if a new routine calls this function, it will fail if the lock is not held.
I use asserts to guarantee future maintenance won't break the code.
Where law ends, tyranny begins -- William Pitt
Code running on mars reboots when it hits an assertion. Simple as that. So what? It's much easier, simpler, and more reliable to just restart than to try and recover. What if the null pointer passed into your code is due to a weird memory overwrite somewhere else? Just reboot.
...but do you plan to support the full resolution of devices like the T3?
Doesn't it make you feel good to know that our freedoms are protected by politicans, lawyers and journalists.
The only valid place to use assertions in a real application is in unit tests. Aside from that, this concept should be in the history books. There is simply no valid reason to use assertions otherwise. Why?
1) In general, programs should not simply terminate because they are not happy. They should recover gracefully and continue on. In the cases where it is appropriate to terminate, an assertion is an exceptionally poor way to handle it.
2) Some say to use them during development. I say no fucking way. It's a cop-out for not using proper logging and unit testing. Do your fucking job and you simply won't need assertions.
3) Why, dear God, why did they add this to the Java language?? LET IT DIE!
Any man who afflicts the human race with ideas must be prepared to see them misunderstood. -- H. L. Mencken
What strikes me as insane is how industry best-practice is to take a foot-shooting language like C++, Java, or C# and incrementally add (and pay for) braces to keep you from being able to point the gun at your foot and pull the trigger -- when you could just not give your programmers guns!
Unit tests are an attempt to duct tape stronger typing and contracts on to languages that are unsuited for them, leading to the necessity of kludges like mock objects and test generators. But no matter what tools you add, test-driven development is going to be painful in a language without built-in support for it.
So then why are languages like Eiffel not more popular? One theory is that schools still believe that programming should be taught as play and so programmers must start with unstructured languages and modularly add good practices. Imagine if engineers were taught like that.
That's not a more accurate statement, it's simply a different one.
Perhaps, but if I'm the application developer and you're the library developer, then that's my decision, not yours.
I might have all kinds of clever diagnostic code running in my application, direct comms with the debugger, other activity going on in different threads, acquired resources, or 101 other reasons that I don't want to kill my application dead, even if your library encounters a serious problem. By all means tell me about the problem, and then if I want to, I can dead-end everything to make it obvious while I'm testing. But don't tell the rest of my application, about which your library has no knowledge, how it should handle an error in one part of the program. That is the worst sort of catastrophic failure, and violates every principle of modularity and encapsulation in the book.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
And consider this:
I can't tell you how many problems I've flushed out of legacy code (and how many misconceptions I've flushed out of my brain) by adding checks like that. The assert takes no thought and only a few keystrokes -- no need to choose a categorization for the error or compose an error message.
What would you report in a case like this, anyway? "Something impossible has happened" or "I must be blind" or "Please call a doctor, I'm hallucinating"?
Assertions are the best way to catch programmer errors related to scope, accidental shadowing, and counterintuitive linguistic issues because those kinds of errors lead to visually and intuitively impossible behavior. Very few programmers will type fifty characters to check for a condition that they're 99% sure is logically impossible, especially if they're worried about performance overhead, and especially if it interrupts their train of thought. We don't blink at fifteen mindless keystrokes.
Fundamentally, though, the best reason to use assertions is that they're the only way to yoke together mathematics and experiment.
Assertions are useful for documenting preconditions in code. E.g., this function should never be passed a NULL pointer. If you do so, you lose, and the program is aborted. The idea is that eventually the code is tested and robust enough that we trust the assertions will all pass, so we turn them off to gain a slight advantage in performance.
-- Man invented God.
...at least C.3 which doesn't make any sense.
That's why you should never use any code that actually does something inside the assert(). You should use this:
int* p = malloc(sizeof(int));
assert(p != NULL);
*p = 0;
My bad, I used assert(malloc()) in previous examples just for lazyness.
Would you believe I went through three years of C++ and java programming and assertions never once came up!?
I'm still confused as to exactly what the benefit of assertions are. I mean what exatly does assert() actually do? In other words what's the benefit of using assert(ptr) rather than if(ptr==NULL) or whatever.
I feel so crippled.
And just on the matter of exiting gracefully. Exiting is never graceful. Any and all errors are abhorent to the user. Having an app bug out without the slightest hint of what went wrong is even worse.
May the Maths Be with you!
Assertion is more to test your logic to make sure it does what it's supposed to do and that it is accessed properly, not to test adverse runtime conditions.
Exception handling is the one you should use for taking care of adverse conditions in production.
I TA'ed for an intro programming course in C++ for 4 semesters at school, and all the time kids would use asserts to verify that user input was in the correct range. And THEN they'd complain when they lost points!
student: "But it IS error-checking!"
me: "Yes, but how would you feel if a program you were using crashed just because you slipped and entered the wrong number?"
student: "Uhhh...."
me: "I'd cry. In fact, I did when I ran your program. It took me a good fifteen minutes to collect myself."
Insightful: 76, Off-Topic: 379, Flamebait: 24, Funny: 152, Interesting: 201, Underrated: 55, Troll: 9, Total: 896
Debug asserts should be fatal. PRoduction assertion failures should be logged.
If you have ever used GTK, they have the worst assertions ever. Everything fails. What you really want to do is ensure that your assertions generally imply implicit assumptions. If func(int a) can accept and work with a 0, assert(a>0) is not an implicit assumption.