Slashdot Mirror


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."

29 of 170 comments (clear)

  1. To save 10-20 minutes, by dtfinch · · Score: 4, Insightful

    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.

    1. Re:To save 10-20 minutes, by Phleg · · Score: 5, Insightful

      Sorry, but this is an extremely naive way of coding, in my opinion. Errors occur for a reason; if you don't do something about their existence, you're likely to start experiencing unexpected problems. Crash early crash often isn't a joke; it's far better to die when you can gracefully than it is to ignore all errors and crash losing data.

      --
      No comment.
    2. Re:To save 10-20 minutes, by Metasquares · · Score: 5, Insightful

      If an assertion can fail under normal circumstances in released code, assert is being misused. IMHO, the idea behind an assertion is to prevent violations of preconditions set down in the code from occurring. These preconditions do not cover runtime conditions, such as memory errors; that's the sort of thing that exception handling should be used for. An assertion indicates something that you are doing wrong rather than a problem with the environment.

  2. Test Drivers by frooyo · · Score: 3, Interesting

    I use them like crazy when I write 'test drivers' for functional units of code (albeit Object Oriented classes etc).

  3. Indubitably by Screaming+Lunatic · · Score: 5, Interesting
    At work we have custom assert, breakpoint, trace, and crash handler code. This is in C/C++. Whenever an assert fires off, it will break in to the debugger if it is present. If not, it will do a stack trace package up a email and send it to our symbol server. The symbol server looks up function names and line numbers and sends out an email to the developers. We get an email within about 5 minutes of when an assert fires on a user's machine.

    Design-by-contract is tha shiznit. It keeps your code base quite stable.

    1. Re:Indubitably by Screaming+Lunatic · · Score: 4, Interesting
      It is super sexy. If Paris Hilton was a coder she would say that it was hot. It's all in house. Using a bunch of Win32 calls. Here's some info:

      Symbol Server and IsDebuggerPresent 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.

  4. (Disabled) assertions suck. by Dr.+Bent · · Score: 5, Informative

    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.

  5. No. by Saeed+al-Sahaf · · Score: 5, Funny

    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
  6. I use Eiffel-style assertions in C++ by ulatekh · · Score: 4, Insightful

    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
    1. Re:I use Eiffel-style assertions in C++ by FuzzyDaddy · · Score: 3, Funny

      Programming by contract is all very nice until your methods start suing one another...

      --
      It's not wasting time, I'm educating myself.
  7. Re:No by ciroknight · · Score: 3, Insightful

    You also must realize, that with Maple, it's quite easy to detect errors in calculations, and in coding. In practical programming with an object oriented language, it's almost essential to have some kind of error handling routines. Whether you use try-catch or the actual "assert" function, or some other error checking setup, it will save you ages in debugging a larger code base.

    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.

    --
    "Victory means exit strategy, and it's important for the President to explain to us what the exit strategy is." G.W.Bush
  8. Yes, but you have to use them properly by c0d3h4x0r · · Score: 4, Interesting

    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.
  9. My Ass Erts by lbmouse · · Score: 5, Funny

    ...when I sit and code too long.

  10. Yes, look into GCC by norwoodites · · Score: 4, Informative

    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.

    --enable-checking=assert,fold,gc,gcac,misc,rtlfl ag ,rtl,tree is fun as it takes 5 days to build a compiler even on a fast computer.

  11. The OS does too little by a1englishman · · Score: 5, Interesting

    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.

    1. Re:The OS does too little by AuMatar · · Score: 3, Insightful

      The problem with the OS doing it is that means the OS enforces too much policy. Lets say I have a multifunction printer hooked up to my PC. The fax fails. WHat should the OS do? SHould it eliminate all access to the device? Just to the fax? Should it cut off scan and copy oo in case the scanner is what broke? What about print, it may have been the printer that broke.

      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.

      --
      I still have more fans than freaks. WTF is wrong with you people?
  12. Depends on the environment! by Dormann · · Score: 3, Insightful
    If you are developing for large, flexible software environments, The best coding practice is to hard-code logic for all situations, right? Write alternate code paths if that float is NaN or if that array size is negative. Catch, throw, and all that.

    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.

  13. Re:(Disabled) assertions suck. Not Always. by AltaMannen · · Score: 4, Insightful

    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).

  14. Assertions are your friend by Alomex · · Score: 4, Interesting

    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.

  15. semantic by BinLadenMyHero · · Score: 4, Insightful

    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);
    }

  16. Abort by file-exists-p · · Score: 3, Interesting


    If assert fails, I abort().

    I use assert to detect the problem instead of detecting its byproducts.

    --
    Go Debian!

  17. Re:assert ==let by AndroidCat · · Score: 3, Funny

    Dartmouth. If you used LET, did the computer really have to do it? They should have been more definite and used a MAKE, FORCE or DOITORDIE statement.

    --
    One line blog. I hear that they're called Twitters now.
  18. Re:They drive me nuts by miu · · Score: 4, Informative

    Assertions do not detect runtime errors, they do not even detect incorrect assumptions about data formating, they detect programming errors. An assertion is a statement you make what the state of some portion of the program at that point, if the library is asserting on you then either the assert (and the library itself) is wrong or your use of the library is wrong, either way the assert has done exactly what it was supposed to do - alerted you to a programming error.

    --

    [Set Cain on fire and steal his lute.]
  19. Re:(Disabled) assertions suck. Not Always. by vadim_t · · Score: 4, Insightful

    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.

  20. Re:Assert, no. Throw, yes. by nytes · · Score: 5, Interesting

    I disagree. To co-opt your analogy, asserts are more like the walk-around you do on your car before you get in to drive away. (Er, you did read the owner's manual for your car, didn't you?)
    e.g.
    assert(CarStillHasFourWheels);
    asser t(HoodIsLatchedDown);

    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).

    --
    -- I have monkeys in my pants.
  21. Re:They drive me nuts by Anonymous+Brave+Guy · · Score: 4, Interesting
    Seems to me that the library is telling you that you are caling it wrong, and you should fix your code.

    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).

    --
    If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
  22. Yell and crap your pants by Brandybuck · · Score: 3, Interesting

    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!
  23. Re:Debug and release builds by Krischi · · Score: 4, Interesting

    Of course, using assertions heavily can incur a significant performance hit, which may or may not be acceptable in your particular application. [...]

    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.

  24. Reliable software uses assert() by digitalEric · · 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.

    assert(foo < columns);
    assert(hash_contains_key(bar, foo));

    is as readable as a

    /* foo is less than the # of columns, and bar is a hashtable which contains a value for the key foo */
    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).