From: Daniel T. on 4 Mar 2010 21:35 "Nevin :-] Liber" <nevin(a)eviloverlord.com> wrote: > "Daniel T." <daniel_t(a)earthlink.net> wrote: > > > In my experience (and it might be just in my domain,) if an > > exception is thrown, then it is because a programmer made an > > unwarranted assumption while writing some particular piece of code > > and the code should be fixed so the exception is no longer thrown. > > (In my problem domain, you are describing ASSERT, not exceptions.) Several people have made comments like this one. I can imagine a domain where just asserting and aborting the program, or allowing a bug that wasn't found during test time to put the program in an undefined state, would be a very bad thing; such systems would use exceptions to do some sort of reset and problem logging. However, that isn't my domain. I style my code after the standard when it comes to exceptions. A thrown exception means that the code that detected the programmer error, is not the code that needs to be fixed. (Precondition violations.) Some who responded like to use exceptions for normal control flow that is designed to deal with user errors. I personally don't think that is appropriate. > I'm confused. In some of your examples, you use STL constructs (such > as vector and string), which can throw. How do you avoid things like > vector and string from throwing exceptions? Good question. It's called being pro-active, for example: I know that bad_alloc will not be thrown because I know how much memory I have to work with, and I keep within that memory footprint. If bac_alloc does get thrown, then that is a bug that must be fixed, not a part of the normal control flow of the program. I know that bad_cast will not be thrown because when I dynamic cast a reference, I know it will succeed. If bad_cast does get thrown, then that is a bug that must be fixed, not a part of the normal control flow of the program. I know that bad_typeid will not be thrown because when I get the typeid of a dereferenced pointer, I know the pointer contains something. If bad_typeid does get thrown, then that is a bug that must be fixed, not a part of the normal control flow. I could write a paragraph like the above for every single exception in the standard (and every exception that my code throws,) but I'm sure you get the idea. (When working in a team, replace "I" with "We" in the above.) Hopefully, this clears up my position on the issue. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel T. on 5 Mar 2010 02:25 Francis Glassborow <francis.glassborow(a)btinternet.com> wrote: > One thing that irritates me with the SESE camp is that many of them > actually do not understand that it is more than just avoiding multiple > exits it is about structuring your code in such a way that a single exit > is natural and not being contrived by having extra variables. > > And the SEME camp contains a good number of people whose code lacks > clarity because they just bail out at any old point. Thank you Francis for being the voice of reason. I think part of the problem is the false dichotomy of the entire discussion. If I ever met a programmer who *never* used multiple exits, or *never* used singe exits, I would ignore him for a fool. The goal is to structure the code well and I tend to structure my code so that I don't *need* multiple exits. The only thing I do that is even remotely controversial is that I tend to add a "result" variable. (As I have already said in this thread, I do this because it makes testing easier.) The people I've worked with routinely tell me that my code is very readable (even people who don't like me will say that my code looks "academic" or like a textbook example,) so I think I'm doing OK as far as code structure is concerned. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mathias Gaunard on 5 Mar 2010 02:28 On Mar 5, 2:35 pm, "Daniel T." <danie...(a)earthlink.net> wrote: > "Nevin :-] Liber" <ne...(a)eviloverlord.com> wrote: > > > "Daniel T." <danie...(a)earthlink.net> wrote: > > > > In my experience (and it might be just in my domain,) if an > > > exception is thrown, then it is because a programmer made an > > > unwarranted assumption while writing some particular piece of code > > > and the code should be fixed so the exception is no longer thrown. > > > (In my problem domain, you are describing ASSERT, not exceptions.) > > Several people have made comments like this one. I can imagine a domain > where just asserting and aborting the program, or allowing a bug that > wasn't found during test time to put the program in an undefined state, > would be a very bad thing; such systems would use exceptions to do some > sort of reset and problem logging. However, that isn't my domain. > > I style my code after the standard when it comes to exceptions. A thrown > exception means that the code that detected the programmer error, is not > the code that needs to be fixed. (Precondition violations.) Trying to allocate a resource and it failing is a programmer error? Interesting point of view, but it doesn't work. Exceptions are not for programming errors, there are for errors that shouldn't happen ideally but may well happen anyway, and still need to be correctly dealt with (at least, if you want to write code of decent quality). For programming errors, you use asserts, which abort the program if a precondition has been violated, because the program is in a state it definitely should never be in, and there is no way to recover from that. > I know that bad_alloc will not be thrown because I know how much memory > I have to work with No you don't. You're likely working on a system with multiple processes running at the same time, and there is no realistic way to predict whether memory allocation would succeed or fail at a given time. Normally, it shouldn't happen; but it may still happen, and you need to deal with it cleanly. (In truth, your operating system probably overcommits anyway, but that wouldn't be the case for sensitive resources or on platforms where memory is sensitive) -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Thomas Richter on 5 Mar 2010 09:09 Daniel T. wrote: > "Nevin :-] Liber" <nevin(a)eviloverlord.com> wrote: >> "Daniel T." <daniel_t(a)earthlink.net> wrote: >> >>> In my experience (and it might be just in my domain,) if an >>> exception is thrown, then it is because a programmer made an >>> unwarranted assumption while writing some particular piece of code >>> and the code should be fixed so the exception is no longer thrown. >> (In my problem domain, you are describing ASSERT, not exceptions.) > > Several people have made comments like this one. I can imagine a domain > where just asserting and aborting the program, or allowing a bug that > wasn't found during test time to put the program in an undefined state, > would be a very bad thing; such systems would use exceptions to do some > sort of reset and problem logging. However, that isn't my domain. Exceptions are rarely used to do some kind of "reset". They are (probably) reported, or (probably) addressed by additional logic that analyses the source of the problem and then addresses the problem. Exceptions are a mechanism that, if point A in a program finds itself in a situation it cannot handle by itself, this problem is reported "upstream" by several layers to the caller to address it. If point A could have fixed the issue, then it rather should do that immediately without the need of reporting it. If the condition is because the program is in an undefined state, then throwing an exception is *not* a good idea. How do you want to fix a problem if all you know is that the program state is *exactly not* well-defined? That is, exceptions are *exactly not* to report undefined program states. This is what assertions are good for. Example for exceptions: An input file is in an invalid format. Report the error to the user, or report the problem upstream to try a different format. Example for exceptions: An algorithm A is supposed on non-negative inputs generated by a second algorithm B. The algorithm A finds a negative number as input. Apparently, then B is buggy. Nothing else can be done at this point. Terminate the program. > I style my code after the standard when it comes to exceptions. A thrown > exception means that the code that detected the programmer error, is not > the code that needs to be fixed. (Precondition violations.) Sorry, you misunderstand. Exceptions are, in the standard, not used to report programmer errors; they are, in no sense, indications that something in the code needs to be fixed. > Some who responded like to use exceptions for normal control flow that > is designed to deal with user errors. I personally don't think that is > appropriate. But that's exactly what exceptions are designed for. Without exceptions, a user error would have to be reported upsteam by return codes. Which means that every caller is *required* to check for return codes all the time, which also means that you (often) cannot use the function return value for anything *but* error codes. Which means code that is less readable and less maintainable - this is *exactly* what exceptions address. >> I'm confused. In some of your examples, you use STL constructs (such >> as vector and string), which can throw. How do you avoid things like >> vector and string from throwing exceptions? > > Good question. It's called being pro-active, for example: > > I know that bad_alloc will not be thrown because I know how much memory > I have to work with, and I keep within that memory footprint. If > bac_alloc does get thrown, then that is a bug that must be fixed, not a > part of the normal control flow of the program. I don't know the domain you're working in, but *usually* you neither have algorithms whose memory footprint can be exactly predicted, nor are you working in environments whose available memory is known exactly in advance. The former applies only to trivial problems, the latter might probably be true in embedded applications. But every multithreading operating system is, by construction, non-deterministic, so you cannot know in advance whether memory will be available or not at a certain point. > I know that bad_cast will not be thrown because when I dynamic cast a > reference, I know it will succeed. If bad_cast does get thrown, then > that is a bug that must be fixed, not a part of the normal control flow > of the program. Simple enough to avoid, but bad_cast is not necessary a "bug". It might also be used to filter out "untypical" input, i.e. the exception could be cought and the input could be handled in some other type. If that is not the case, let the exception unwind up to main() where an unexpected exception will be reported and the program will terminate. > I know that bad_typeid will not be thrown because when I get the typeid > of a dereferenced pointer, I know the pointer contains something. If > bad_typeid does get thrown, then that is a bug that must be fixed, not a > part of the normal control flow. See above. Not necessarily so. If bad_typeid is thrown and that is *not* part of the designed program flow, then the program should be terminated. > I could write a paragraph like the above for every single exception in > the standard (and every exception that my code throws,) but I'm sure you > get the idea. No. I don't, sorry. I have the strange feeling that you got "exceptions" backwards. "exceptions" are something very different from "assertions" and program bugs. They are a useful construction for *correct* but *rare* global flow control of an algorithm, to address situations were you do not want to pass return codes through several layers of code. Exceptions are rather ill-designed to report program bugs because you could still catch them and continue going. So long, Thomas -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Mathias Gaunard on 5 Mar 2010 20:58
On 6 mar, 02:09, Thomas Richter <t...(a)math.tu-berlin.de> wrote: > Exceptions are rarely used to do some kind of "reset". They are > (probably) reported, or (probably) addressed by additional logic that > analyses the source of the problem and then addresses the problem. > Exceptions are a mechanism that, if point A in a program finds itself in > a situation it cannot handle by itself, this problem is reported > "upstream" by several layers to the caller to address it. Exceptions are not just a mere way of reporting errors to upper layers. They also allow to properly cancel whatever current operations the exception happened in the middle of, assuming your code is exception-safe. (what cancel exactly means depends on the level of exception-safety) -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |