2

For example, I have a method which accepts some arguments like

method1(int i)

the argument int should be either 1 or 2

I can use assert (i == 1 || i ==2)

or throw exception if (!(i==1) || (i==2)) throw std::exception

which one is better. I am always confused about assert vs explicit throw.

Adam Lee
  • 24,710
  • 51
  • 156
  • 236
  • 1
    Neither? I would just recommend returning some error code and handling it that way. In my opinion, throwing exceptions should be reserved for exceptional behavior. – Cory Kramer Feb 13 '15 at 22:53
  • 3
    Maybe your argument should be an enum. – Brian Bi Feb 13 '15 at 22:54
  • 3
    Or boolean might be a better option – Ed Heal Feb 13 '15 at 22:54
  • 3
    It all depends on the context. Throwing a `std::invalid_argument` might be applicable. – Daniel Kamil Kozar Feb 13 '15 at 22:54
  • 1
    Use `assert` for programmer error, exceptions for others. – Deduplicator Feb 13 '15 at 22:59
  • 1
    In the general sense, `assert` is typically used to detect a *programing* problem; A condition that, given everything is hooked up properly, should never happen. Asserts fail hard; They immediately abort the program. Exceptions, on the other hand, are used to detect *data* problems; conditions which aren't normally true, but which could be do to elements outside one's control (like dynamically generated values). They give the caller an opertunity to detect this problem and react accordingly. – aruisdante Feb 13 '15 at 22:59
  • Duplicate: http://stackoverflow.com/questions/117171/design-by-contract-tests-by-assert-or-by-exception – Deduplicator Feb 13 '15 at 23:01
  • Also keep in mind that the stdlib implementation of `assert` is only compiled in debug mode for performance. Further indicating its indended use is to detect programing/logic errors, not 'expected but exceptional' run-time failure conditions. To qote the docs: `Therefore, this macro is designed to capture programming errors, not user or run-time errors, since it is generally disabled after a program exits its debugging phase.` – aruisdante Feb 13 '15 at 23:39

3 Answers3

1

It really depends on the situation.

There are four major groups of error handling:

  1. assert - used to deal with programming errors ("We don't expect this function to get a NULL pointer, and if it does, it's because some other part of our code is broken, and it should NEVER happen"). If the assert wasn't there, the code would probably crash, loop forever, or otherwise "fail".

  2. exceptions - such as std::invalid_argument - this is more used when the program EXPECTS things to go wrong, and there is some way to "try again". More likely when the actual user is using the program wrong - e.g. inputs from keyboard/file, etc. As the name states, this should be an "exception" - something unusual and unexpected.

  3. return value - when an error is entirely likely (trying to see if the serial port is on port COM1, COM2, COM3 or COM4 or "is the result of the equation matching what I expect yet?")

  4. Let it crash - if the inputs are wrong, the application runs out of memory, etc, just crash. It may seem like a rough method, but sometimes there's not much better you can do anyway - what are you going to ACTUALLY do in the middle of your compiler if some linked list is broken and the next node is not pointing at your special sentry pointer, but to NULL? Printing a message may be a little better, but not a huge amount.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1

Is the integer passed to method1 always going to be done so by a programmer, or might it be passed in by the users of your application?

Assert, for example if your code looks like this:

int i;
if ( condition ) {
    i = 1;
}
else {
    i = 3;
}

method1(i);

If this is the case, you'd likely want to use an assert, because it indicates you (the programmer) has made an error. If i = 3, you want your program to blow up and make it obvious there is a problem in your code, so you can catch it before you release it to your clients.

Throw an exception, on the other hand, if your code looks like this:

int i;
cin >> i;
method1(i);

You're passing the user's input to the function. You can't anticipate what they might enter. So if it's an invalid value, you should throw an exception or return an error code and handle it accordingly (e.g., print out a message to the user saying they have entered an invalid number).

Julian
  • 1,688
  • 1
  • 12
  • 19
  • my method1 is an API which can be used by 3rd party. you suggested to use exception in this case? – Adam Lee Feb 13 '15 at 23:16
  • Typically, checking the API valid argument is an exception. Checking your own and customers "correct use" is an assert - for example, you may assert that some data structure that you (should) have created does not have a NULL pointer in it. – Mats Petersson Feb 13 '15 at 23:29
0

Generally asserts are checked in debug builds but not release builds. If you want to save time and skip the check in your final released code, then asserts are the way to go. If your function needs to blow up in the face of unexpected input even in release, then the exception may be the way to go.

Of course the details of exactly what you should do for error conditions will vary with context beyond what was provided in your example.

Scott Pedersen
  • 1,311
  • 1
  • 10
  • 19