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

26 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 AuMatar · · Score: 2, Insightful

      The value of an assert si that you can #define assert() to mean different things in different builds. In development mode, assert may halt the system and print an error. In release builds, assert can write an error file and continue without comment. Or just be defined as a no-op.

      --
      I still have more fans than freaks. WTF is wrong with you people?
    3. 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.

    4. Re:To save 10-20 minutes, by Anonymous Coward · · Score: 1, Insightful

      Assertions are not to be used for catching problems with user input. "Assert" means that you are relying on the proper behaviour of other code. The assert statement is a plausibility check for code correctness, not user input. The behaviour after an assert-failure should be to never overwrite existing data, to save volatile data to a new area and to stop the program as soon as possible. You're dealing with a programmer error. That is the kind of error you're not supposed to have under control. Detecting it is as good as it gets unless you have redundant systems with independently written code.

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

      There are preconditions, and there are preconditions. Then there are preconditions.

      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, which are in effect only during development, debug, and test. (This implies that test should occur both with and without assertions.) I want to catch every failure of design assumptions during this phase. During deployment, I only want to fail hard when the consequences of hard failure are less onerous than the consequences of soft failure, so I use different code (generally, a top-level exception handler) than I do for development-phase assertions, which are generally puke-and-die.

      --
      -I like my women like I like my tea: green-
  2. They drive me nuts by n1ywb · · Score: 2, Insightful

    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
    1. Re:They drive me nuts by treerex · · Score: 2, 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 error condition on bogus input. But for tight libraries this extra checking may not be useful, and the assertions work fine during development to ensure you're not doing anything boneheaded.

    2. Re:They drive me nuts by miu · · Score: 2, Insightful
      We know that programing errors make it into shipped code. Ignoring that reality is not a sensible option, so we must code defensively.

      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 debugging memory allocators, clarify, electric fence, etc. Such tools are used in an entirely different way than error handling or defensive coding.

      --

      [Set Cain on fire and steal his lute.]
  3. 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
  4. 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
  5. Re:(Disabled) assertions suck. by dtfinch · · Score: 2, Insightful

    Assertions can turn little errors into big errors.

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

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

  8. YES ... For large applications by JPyObjC+Dude · · Score: 2, Insightful

    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

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

    1. Re:semantic by Anonymous Coward · · Score: 1, Insightful

      Code that never actually does the malloc is worse still.

      #define _NDEBUG
      #include

      main()
      {
      int *p; ...
      assert((p=malloc(sizeof int))!=NULL);
      *p=0;
      }

      I believe with the standard version of assert(), the expression is never evaluated, so p is uninitialised.

    2. Re:semantic by AuMatar · · Score: 2, Insightful

      You mean

      #if NDEBUG
      void assert(int cond){}
      #else
      void assert(int cond){ //real code ehre
      }
      #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.

      --
      I still have more fans than freaks. WTF is wrong with you people?
  10. Re:(Disabled) assertions suck. by Bastian · · Score: 2, Insightful

    Assertions can turn little errors into big errors.

    It turns out that that's exactly what assertions are supposed to do.

  11. There are rules for this by Ozwald · · Score: 2, Insightful

    - 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

  12. 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?
  13. 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.

  14. Re:(Disabled) assertions suck. by Anonymous+Brave+Guy · · Score: 2, 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. :-(

    --
    If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
  15. Re:(Disabled) assertions suck. Not Always. by Mr.+McGibby · · Score: 2, Insightful

    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
  16. Re:(Disabled) assertions suck. by Metasquares · · Score: 2, Insightful

    I think that the idea behind them is to turn little errors into big errors so that a "little" error to the program (loaded garbage data for an account balance, for example) becomes a big error before any harm is done. It is generally accepted that errors that halt execution are preferrable to logic errors, which seems to be the philosophy behind assert().

  17. Aborting the app is not the library's choice... by Anonymous+Brave+Guy · · Score: 2, Insightful
    I think a more accurate way to state that would be: No library code should ever cause the whole application to abort when the application is being used by an end user.

    That's not a more accurate statement, it's simply a different one.

    Under development it's a completely different situation. The top goal isn't running cleanly at all cost; the top goal is finding anything that might be a bug.

    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.