

Do Programmers Actually Use Assertions? 170
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."
To save 10-20 minutes, (Score:5, Insightful)
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.
Re:To save 10-20 minutes, (Score:5, Insightful)
Re:To save 10-20 minutes, (Score:2)
I've lost data to assert() checks in other people's software, over trivial things that could have been safely ignored. I've also recovered from crashed software by loading it in a debugger and skipping over the failed instruction. I've never lost data that would have been saved by a fatal assert().
Re:To save 10-20 minutes, (Score:5, Insightful)
Re:To save 10-20 minutes, (Score:3, Insightful)
There are preconditions which are dictated by the design, a priori conditions which should not be violated, by design. It is easy to identify two broad categories of subcases:
There are preconditions which, when violated, will cause a catastrophic failure of the code which assumes them.
There are preconditions which, when violated, may or may not cause a degraded mode of operation.
I use conditionalized asserts liberally,
Re:To save 10-20 minutes, (Score:3, Insightful)
Re:To save 10-20 minutes, (Score:2)
This is ok for production systems, where you are accessing a database or something like that, but otherwise I'd just output debug info within <!-- --> pairs.
I don't really use assertions except that I write a lot of code to deal with unusual input in a non-fatal fashion.
You are really, really asking for trouble coding that way. Not only will it make your software unneccesarily slow, it will also mask problems on different
unit testing only (Score:3, Interesting)
I only use assertions in unit test code such as here [junit.org] and here [nunit.org].
Mod parent up! (Score:2)
Re:Mod parent up! (Score:2)
Test Drivers (Score:4, Interesting)
No (Score:2)
Re:No (Score:4, Insightful)
I think the newer Object Oriented languages (Java, C#, Objective C) have great error handling that foolishly gets ignored when younger coders go to work, myself included.
Re:No (Score:2)
That's because Maple uses plenty of assertions. I don't suppose you have to deal with being passed a null pointer or not having enough memory, do you? The coders of Maple took care of these situations with plenty of error-handling code, so you're guaranteed that what you think is a number is indeed a number.
Debug and release builds (Score:3, Interesting)
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 (exclu
Re:Debug and release builds (Score:4, Interesting)
Interestingly, the performance hit seems to be almost negiglible on an AMD Opteron in 64-bit mode with gcc 3.4, as long as the assertions themselves are trivial. AMD must have done some really nice things with the branch prediction unit. Way to go.
And yes, I do agree that assertions belong into production code. I cannot count the number of times when they have saved our butts and exposed design or coding flaws. The "impossible" can and does happen more quickly than people would make you believe in general.
Re:Debug and release builds (Score:2)
For one-off assertions at strategic points in your code, sure. The potential problems start when you have a "one-off" assertion that's tested inside nested loops and the like. As with so many performance issues, it's not what you do, it's where (and how often) you do it...
Indubitably (Score:5, Interesting)
Design-by-contract is tha shiznit. It keeps your code base quite stable.
Re:Indubitably (Score:2)
Re:Indubitably (Score:3, Interesting)
You don't need an SDK to implement structured exception handling.
Enjoy,
Re:Indubitably (Score:5, Interesting)
Symbol Server [microsoft.com] and IsDebuggerPresent [microsoft.com] and look in imagehlp.h.
Our crash handler works similiar to Netscape/Mozilla talkback.
Maybe someday I'll put together something equivalent at home for Linux.
Re:Indubitably (Score:2)
(Disabled) assertions suck. (Score:5, Informative)
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.
Re:(Disabled) assertions suck. (Score:3, Insightful)
Re:(Disabled) assertions suck. (Score:3, Insightful)
It turns out that that's exactly what assertions are supposed to do.
Re:(Disabled) assertions suck. (Score:3, Insightful)
More seriously, assertions that can be disabled can potentially hide little errors altogether. Consider what happens if evaluating the condition for your assertion has side effects, but in release builds that condition is never evaluated. Oh, dear: now you can test quite happily on your diagnostic build, but the one you ship to your customer has an extra bug. :-(
Re:(Disabled) assertions suck. (Score:3, Insightful)
Re:(Disabled) assertions suck. (Score:2)
Re:(Disabled) assertions suck. Not Always. (Score:5, Insightful)
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).
Re:(Disabled) assertions suck. Not Always. (Score:5, Insightful)
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.
Re:(Disabled) assertions suck. Not Always. (Score:3, Insightful)
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 check
Re:(Disabled) assertions suck. Not Always. (Score:2)
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
Re:(Disabled) assertions suck. Not Always. (Score:2)
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....
They drive me nuts (Score:3, Insightful)
Re:They drive me nuts (Score:3, Insightful)
I think it's rediculous that a library call should cause the calling application to exit because of a failed assertion.
Really? Seems to me that the library is telling you that you are caling it wrong, and you should fix your code. Which is, of course, the whole point.
Assertions are a Good Thing on many levels, especially when developing new code, since they will enforce the invariants in your API during development. Obviously you would have include conditional code that checks arguments and returns an
Re:They drive me nuts (Score:5, Interesting)
Perhaps, but no library code should ever cause the whole application to abort, ever. There are few absolutes in software development, but this is one of them.
The library code is entitled to screw up whatever internal data it likes, and to give me whatever garbage out if I put garbage in, but it is not allowed to screw the rest of my program (and thus to circumvent any graceful-shutdown error-handling system I have in place there).
Re:They drive me nuts (Score:2)
Well, nothing, I suppose, but why would you ever want to use the one that kills your app when some internal test fails?
It doesn't help you, the library user, to determine what the problem was, other than possibly which API call actually blew up. Whether the data you gave to that one was the cause of the explosion is a different question, of course.
If you're talking about NDEBUG, presumably we'r
Re:They drive me nuts (Score:2)
I'm not sure my customer will understand that, as I explain to them why we've just lost their whole day's data when our software crashed...
Not at all. What
Aborting the app is not the library's choice... (Score:3, Insightful)
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 yo
Re:Aborting the app is not the library's choice... (Score:2)
Blockquoth the AC:
Well, assert is indeed standard, but the principle is much more general, and I've never yet worked on a production project that actually used the standard macro rather than a customised version.
Re:They drive me nuts (Score:2)
Perhaps a decade ago, but not today. In all that time, I have neither seen a real world project, nor talked to a real world programmer, that suggested this was acceptable practice.
Re:They drive me nuts (Score:5, Informative)
Re:They drive me nuts (Score:2)
Re:They drive me nuts (Score:2)
If you are testing for live errors with asserts then you are wrong, if you are still checking for programing errors in live runs then you are wrong. Asserts and error handling are two very different things.
Re:They drive me nuts (Score:3, Insightful)
I should clarify that. In container classes, searches, or any utility code I assert all sorts of things. Every time I add, seach, iterate, delete, etc. I check all sorts of internal consistency. Live code can generally not do that at anything near the same attention to detail, the error handling code is present, but at a much coarser level. Asserts are a tool like debuggi
Re:They drive me nuts (Score:2)
No, the correct way to do it is to test all your functions/methods/subroutines/whatever enough so that this kind of shit never happens.
Yes (Score:2)
No. (Score:5, Funny)
Re:No. (Score:2, Funny)
Yeah, exactly. My code always works fine the first time, and has plenty of undocumented "features" to boot.
Re:No. (Score:2, Funny)
Re:No. (Score:3, Informative)
Re:No. (Score:2)
A Bug. [navy.mil]
I use Eiffel-style assertions in C++ (Score:4, Insightful)
I read the Eiffel [eiffel.com] book, but I've never been in a position to actually write code in it. But I love the concept of programming by contract [eiffel.com].
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 [sourceforge.net].
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.
Re:I use Eiffel-style assertions in C++ (Score:3, Funny)
Languages vs Add-Ons (Score:2)
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,
Yes, but you have to use them properly (Score:5, Interesting)
Dependable Software Research Group? (Score:3, Funny)
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
Updated (Score:2)
-Hope
I use them (Score:2)
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...]
My Ass Erts (Score:5, Funny)
Yes, look into GCC (Score:5, Informative)
--enable-checking=assert,fold,gc,gcac,misc,rtlf
The OS does too little (Score:5, Interesting)
Re:The OS does too little (Score:4, Insightful)
Timeouts? How does the OS know whats a reasonable timeout? Program A may expect data over TCP every 30 seconds or it signifies a failure- for example straming data. Program B may be a telnet session being used infrequently. It may not have data for minutes, even hours. WHat timeout should the OS enforce? When it occurs, what should the OS do- shut down the connection? Ping the other machine? Send a keepalive message?
The OS *can't* handle these because every application requires different handling. Adding in such behavior would make it impossible to write apps that need other behavior.
The correct answer is not to push it into the OS. Its to write better abstractions and libraries on top of the OS, so programmers can reuse the code and not have to write the same program repeatedly. For example, I use my own networking library that replaces the recv() with a custom recv. My version loops calling recv on the socket until either n bytes have been read, an error occurs, the socket is closed, or a timeout (passed in as an int) goes up. It then returns what condition occurs to the caller.
Other layers then go from there. An HTTP or FTP layer would handle those timeouts and failures in a standard way. Some situations may require it to chain an error on up saying the protocol layer failed. And so on and so forth. THis allows maximum flexibility and reuse of all levels, because all layers leave the policy decisions up to the calling code rather than making their own. If each layer decided how to handle every situation, you'd end up having to rewrite each layer for each application, the same solutions would not be applicable. Worse, some applications would need different decisions for different parts of the application. Then you have a real nightmare.
Re:The OS does too little (Score:2)
Just to say, the computer doesn't see a "multifunction printer". It just sees a USB hub with several devices connected. If the fax fails, then it's just that device that has failed.
Re:The OS does too little (Score:2)
Re:The OS does too little (Score:2)
What am I missing?
Re:The OS does too little (Score:2)
Depends on the environment! (Score:3, Insightful)
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.
YES ... For large applications (Score:3, Insightful)
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
Assertions are not error-handling (Score:3)
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
Re:Assertions are not error-handling (Score:2)
IE JavaScript and many other IE frameworks are poorly written as a trade off for speed. For instance, any
Wait a minute... (Score:2, Funny)
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?
Assertions are your friend (Score:5, Interesting)
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.
semantic (Score:5, Insightful)
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);
}
Re:semantic (Score:2)
Re:semantic (Score:3, Informative)
if(malloc() != NULL) {
perror("malloc");
exit(1);
}
Again, assert() is for checking for situations that should never hapen (but can happen by a fault in programming logic, that the assert() is made to catch), not for possible runtime errors.
Re:semantic (Score:3, Insightful)
#if NDEBUG
void assert(int cond){}
#else
void assert(int cond){
}
#endif
In that case, yes, the malloc would probably never be executed, depending on how the compiler optimizes. For this reason, assert calls should NEVER call functions, and should NEVER have side effects.
duh! (Score:2)
int* p = malloc(sizeof(int));
assert(p != NULL);
*p = 0;
My bad, I used assert(malloc()) in previous examples just for lazyness.
Abort (Score:4, Interesting)
If assert fails, I abort().
I use assert to detect the problem instead of detecting its byproducts.
--
Go Debian!
There are rules for this (Score:3, Insightful)
- 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
How accurate can this survey be? (Score:2)
Re:How accurate can this survey be? (Score:2, Funny)
Heck yes. (Score:2)
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
Re:Heck yes. (Score:2)
However you counted all the assertions that are commented out as well.
Assert, no. Throw, yes. (Score:2)
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
Re:Assert, no. Throw, yes. (Score:5, Interesting)
e.g.
assert(CarStillHasFourWheels);
asse
These are assumptions that the program, once it is debugged, should be able to rely upon. They check that the program in internally consistent. However, it pays during debugging to have the program test those assumptions. It could just be that what you assumed to be true, isn't.
When an assumption proves to be wrong (the assert fires) the program stops and tells you where the fault was found, lets you bring up a debugger, etc.
Checks are a different thing from asserts. Checks should, once the program is released, keep the program from processing corrupt/illegal data, when such data might be expected (like input from an operator). If your program is (truely) internally consistent, then only the inputs (and status of output operations) should need to be checked for the program to run.
You never turn off checks in production code, but at some point you can take off the training wheels (assertions).
And before anyone can jump on me about assuming anything while programming, take a look at your own code. Unless you test every freakin' index and/or pointer every freakin' time you use it, you are making assumptions on almost every line (at least, with C/C++ code).
Assertions are good (Score:2, Informative)
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 param
Yes (Score:2)
Re:Yes (Score:2)
Re:Yes (Score:2)
Re:Hey! The text editor looks good... (Score:2)
Re:Hey! The text editor looks good... (Score:2)
Fortunately, I had written an easily-resizable text display to start with, so I'd already done most of the heavy work.
Yell and crap your pants (Score:4, Interesting)
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.
Asserts are for people, too (Score:2, Interesting)
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 e
Reliable software uses assert() (Score:5, Interesting)
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).
Well... (Score:2)
Avoid future issues (Score:2)
I use asserts to guarantee future maintenance won't break the code.
lol...People still use assertions? (Score:2)
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
Re:lol...People still use assertions? (Score:2)
Re:assert ==let (Score:3, Funny)