Prev: Can there be parallel initialization of global variables in C++0x?
Next: Container adapter to treat a sorted vector as a set
From: wij on 1 Jun 2010 22:51 >From a different site, a programmer asked for proper coding standard (error handling) for a common program scenario: initialize(); while (true) { Message msg,out; receive(msg); process(msg,out); send(out); } I thought it would be very difficult to throw std::exception classes to handle all thinkable possible exceptional condition. This opinion has wide effect to C++ programs. My argument is that the catch handler won't be able to tell what had actually happened and handle it properly. E.g. initialize(); while(true) { try { Message msg,out; try { receive(msg); } catch(const std::exception& e) { // Instead of rethrow or ignore, what can be done here reliably to handle // std::exception or others? } process(msg,out); send(out); } catch(const std::exception& e) { // Instead of rethrow or ignore, what can be done here reliably to handle // std::exception or others? } } Say if I caught std::invalid_argument from receive(msg), does it really mean msg is invalid? The same argument for others e.g. domain_error,length_error, out_or_range,range_error,overflow_error,.., and underflow_error. If the std::invalid_argument is caught in the second catch handler above, the picture would be even more complex. So a coding standard forbids using throw and favors return is simply practical from this point view. Instead, most programs using throw is potentially buggy. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Goran on 2 Jun 2010 03:57 On Jun 2, 3:51 pm, w...(a)seed.net.tw wrote: > >From a different site, a programmer asked for proper coding standard > > (error handling) for a common program scenario: > > initialize(); > while (true) { > Message msg,out; > receive(msg); > process(msg,out); > send(out); > > } > > I thought it would be very difficult to throw std::exception classes > to handle all thinkable possible exceptional condition. This opinion > has wide > effect to C++ programs. > > My argument is that the catch handler won't be able to tell what had > actually > happened and handle it properly. E.g. > > initialize(); > while(true) { > try { > Message msg,out; > try { receive(msg); } > catch(const std::exception& e) { > // Instead of rethrow or ignore, what can be done here reliably > to handle > // std::exception or others? I don't know, it's your problem. You failed to receive message, what do you want to do about it? > } You placed that try/catch block rather badly. You try to receive, that fails, but you try to process msg. That doesn't seem right. This is because you caught the exception too early. > process(msg,out); > send(out); > } > catch(const std::exception& e) { > // Instead of rethrow or ignore, what can be done here reliably to > handle > // std::exception or others? > } I don't know, it's your problem. You failed to receive message, what do you want to do about it? > > } > > Say if I caught std::invalid_argument from receive(msg), does it > really mean > msg is invalid? You really have to ask the person who decided to throw invalid_argument from receive. There is no general response to that question. But in general, you should not throw such a general error. Instead, you should throw an exception object that explains the error in best possible terms. > The same argument for others e.g. > domain_error,length_error, > out_or_range,range_error,overflow_error,.., and underflow_error. > If the std::invalid_argument is caught in the second catch handler > above, > the picture would be even more complex. > > So a coding standard forbids using throw and favors return is simply > practical > from this point view. Instead, most programs using throw is > potentially > buggy. No, not really. A counter example: bool receive(MSG_TYPE& msg); if (!receive(msg)) { // What happened? Was some argument invalid, was there overflow...? // from one bool, you don't know, just like you don't know // from std::exception. } Understanding errors when they happen is not easy regardless of mechanism you use, but exceptions easily offer a better way of explaining the error than error-return, simply because you can create a full-fledged object that contains any info you might want. With error-return, getting competent error info is much, much more work. At any rate, you should not be throwing base exception types, they are equivalent to if (!f()) now_what(); But, enough talk. Here's what you could do instead: class receive_error ... {...}; // be more specific, if you wish (you should be) class send_error ... { ... }; // etc. initialize(); while (true) { try { Message msg,out; receive(msg); process(msg,out); send(out); } catch(const exception& e) { log_reception_cycle_error(e); } } void log_reception_cycle_error(const exception& e) { // use exception.what() to log textual representation std::cout<<"something went wrong: "<<e.what()<<endl; // you may use dynamic_cast to get to a specific exception type, e.g. if (dynamic_cast<const receive_error*>(&e)) lor_receive_error(dynamic_cast<const receive_error&>(e)) } You might use multiple catch clauses instead of a function, too. Or, you can use mix-in derivation to attach your specific interface to exception classes and then dynamic_cast to get that info. Or you can use boost::exception to arbitrarily "enrich" info carried by the exception object. IOW, you can do all sorts of things to get as finely-grained error info as you wish. Achieving the same with error-return is way too much harder. Goran. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Randy on 2 Jun 2010 05:06 On Jun 2, 9:51 am, w...(a)seed.net.tw wrote: [snip] > > I thought it would be very difficult to throw std::exception classes > to handle all thinkable possible exceptional condition. This opinion > has wide > effect to C++ programs. > > My argument is that the catch handler won't be able to tell what had > actually > happened and handle it properly. E.g. > [snip] > Say if I caught std::invalid_argument from receive(msg), does it > really mean > msg is invalid? The same argument for others e.g. > domain_error,length_error, > out_or_range,range_error,overflow_error,.., and underflow_error. > If the std::invalid_argument is caught in the second catch handler > above, > the picture would be even more complex. > > So a coding standard forbids using throw and favors return is simply > practical > from this point view. Instead, most programs using throw is > potentially > buggy. > So how would the situation be any different if the called function returned an error code of, say for example, -3? The bottom line, IMHO, is that a called function's use of either exceptions or return codes must be documented in order to know what they mean. Neither has any inherent meaning in and of itself, only what the function defines them to mean. Randy. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Francis Glassborow on 2 Jun 2010 05:06 wij(a)seed.net.tw wrote: >>From a different site, a programmer asked for proper coding standard > (error handling) for a common program scenario: > > initialize(); > while (true) { > Message msg,out; > receive(msg); > process(msg,out); > send(out); > } > > I thought it would be very difficult to throw std::exception classes > to handle all thinkable possible exceptional condition. This opinion > has wide > effect to C++ programs. > > My argument is that the catch handler won't be able to tell what had > actually > happened and handle it properly. E.g. > > initialize(); > while(true) { > try { > Message msg,out; > try { receive(msg); } > catch(const std::exception& e) { > // Instead of rethrow or ignore, what can be done here reliably > to handle > // std::exception or others? > } > process(msg,out); > send(out); > } > catch(const std::exception& e) { > // Instead of rethrow or ignore, what can be done here reliably to > handle > // std::exception or others? > } > } > > Say if I caught std::invalid_argument from receive(msg), does it > really mean > msg is invalid? The same argument for others e.g. > domain_error,length_error, > out_or_range,range_error,overflow_error,.., and underflow_error. > If the std::invalid_argument is caught in the second catch handler > above, > the picture would be even more complex. > > So a coding standard forbids using throw and favors return is simply > practical > from this point view. Instead, most programs using throw is > potentially > buggy. You have not made your case. If you can return an error code you can throw and equally descriptive object (actually good design will allow the object to be more descriptive. BTW only the most naive programmer thinks that exceptions are limited to the standard exception classes. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Pedro LamarĂ£o on 2 Jun 2010 16:54
w...(a)seed.net.tw wrote: > Say if I caught std::invalid_argument from receive(msg), does it > really mean > msg is invalid? It should. To argue that the thrower might actually be mistaken or lying is not to argue against the communication mechanism, but rather to reflect on a fundamental problem with communication itself. If we receive the EINVAL return value from a function, does it really mean the argument is invalid? There is no difference between returning objects or throwing objects in respect to how much meaning this exchange has to the sender or receiver. -- P. [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |