From: Bart van Ingen Schenau on
On Feb 8, 10:12 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
>
> So if the following holds:
>
> * A no-throw function can, without functional harm, be declared throw()
> since such function must throw nothing, compared to a throw( MyException
> ) that can throw more than just MyException due to templates.
>
> If that holds, then I claim an optional feature in the compiler can, by
> means of static checking during compile-time, help finding no-throw
> functions that throws anyway. This optional feature would be no
> disadvantage, but only an enhancement helping programmers writing
> exception safe code.

A compiler *could* offer the static checking of no-throw functions as
an extension, but you will very quickly run into practical problems.

For example, should the compiler, with the feature enabled, complain
about this function:

void write_to_log(char* text) throw()
{
FILE* logfile = fopen("/var/log/mylogs", "a");

fprintf(logfile, "%s", text);
fclose(logfile);
}

None of the functions used here have a no-throw specification, so the
compiler must assume they can throw an exception (unless the compiler
has special knowledge about these functions, but then just substitute
simple wrappers from an internal, company-specific library).

The only way around that is to change the declaration of *every*
function that is known not to throw any exceptions, which is a
prohibitive amount of work.

{excess quoting deleted --mod}
Bart v Ingen Schenau


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Martin B. on
DeMarcus wrote:
>>(....)
>>
>> BTW, don't you trust e.g. standard lib/booost implementors to do the
>> right thing? 'cause they do, much more often than I. Their code is
>> better than mine if nothing else because there's so many eyes on their
>> code, and so little on mine ;-).
>>
>
> I trust the boost implementors fully, I mean, it was one of the founders
> of boost that published the idea of exception safety guarantees; the
> technique I'm now working hard to conform to.
>
> Nevertheless, just because they're renowned C++ experts, that doesn't
> stop me from proposing enhancements to their ideas.
>
> So if the following holds:
>
> * A no-throw function can, without functional harm, be declared throw()
> since such function must throw nothing, compared to a throw( MyException
> ) that can throw more than just MyException due to templates.
>

If throw() is enforced during runtime - i.e. there is an implicit
catch(...)+handler added to each such function - this can have
performance implications depending on the platform.

> If that holds, then I claim an optional feature in the compiler can, by
> means of static checking during compile-time, help finding no-throw
> functions that throws anyway. This optional feature would be no
> disadvantage, but only an enhancement helping programmers writing
> exception safe code.
>
> Please give your comments on this.
>

I fully agree that some mechanism to statically enforce/analyse the
no-throw guarantee would be very welcome!


br,
Martin

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Goran on
On Feb 8, 10:12 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> > Yes, that seems possible. Note, however that something innocuous like
> > std::string s("well now") might throw (bad_alloc is my favorite when
> > talking exceptions ;-)). Or, many calls to STL might throw. And
> > standard library does not use exception specification, nor do many
> > others. So one innocuous library call somewhere and your own spec
> > becomes invalid (think maintenance). (I guess there are reasons why
> > standard and other libraries don't use throw() and that this is
> > related to the spec of throw() and history.)
>
> Maybe I'm slow but I still don't get it. According to the exception
> safety rules, a no-throw function like the destructor, pop, etc. must
> never throw. Then why on earth can't we put throw() on those functions
> since it's a run-time check anyway (and wouldn't break any current code)?

Because, IIRC, there's an additional run-time cost when you declare
function to be no-throw: compiler will generate, effectively a try/
catch for you and call unexpected() if that happens ( that's the
historical reason I was hinting at; you can't change history ;-) ). So
performance-wise, indiscriminate use of throw() is not the best of
ideas. (At this point, we should look at the generated disassembly of
some compilers, with throw() and without throw ;-).)

> >> Let's take a good example. Nowhere can I find proper documentation
> >> whether std::vector's pop_back() throws or not.
>
> > True, you don't see it. Practical answer: it's a nothrow operation.
> > Practical thinking that relates to this, and applies to library
> > writer: poping is cleanup and cleanup must not throw. I know of no
> > implementation where that could throw, and would consider it
> > implementation quality issue if it could. For example, do you know
> > that pop_back in a vector never changes allocated storage? Downside of
> > that is that once you reach some high-mark of elements, you don't
> > never free. But the alternative is worse: if pop-back tried to
> > reallocate, it would have a failure mode; we don't want that.
>
> You are right, but now you're talking out of experience. Not everyone
> has a vast experience, and it can still be difficult to guess whether a
> function is no-throw or not. What would you say about this function for
> instance?
>
> someonesFile.close();
>
> It probably should be no-throw, but who knows what the inventor had in
> mind writing this File class?

Yes, it should be a no-throw operation in my book as well. I'd
check ;-). I'd probably live just as fine with a library where there
would be no close operation at all (that is, d-tor would close the
file and d-tor must not throw, so...). There's also at least one
library who throws from close, but who try/catch calls to close in
their d-tors. That's IMO the best solution: in a rare case where you
actually want to catch such failures, you can do it; for "normal" use
cases, library swallows exception for you. Furthermore, close might be
virtual (it in case of said library), so you can override close to get
"smart" if need be.

In general, I find that for major libraries, cleanup operations are
nothrow operations - that's a question of quality of said libraries.
When I am not sure, I add a try/catch of my own. But that's in my
experience a __rare__ case.

> > BTW, don't you trust e.g. standard lib/booost implementors to do the
> > right thing? 'cause they do, much more often than I. Their code is
> > better than mine if nothing else because there's so many eyes on their
> > code, and so little on mine ;-).
>
> I trust the boost implementors fully, I mean, it was one of the founders
> of boost that published the idea of exception safety guarantees; the
> technique I'm now working hard to conform to.
>
> Nevertheless, just because they're renowned C++ experts, that doesn't
> stop me from proposing enhancements to their ideas.
>
> So if the following holds:
>
> * A no-throw function can, without functional harm, be declared throw()
> since such function must throw nothing, compared to a throw( MyException
> ) that can throw more than just MyException due to templates.
>
> If that holds, then I claim an optional feature in the compiler can, by
> means of static checking during compile-time, help finding no-throw
> functions that throws anyway. This optional feature would be no
> disadvantage, but only an enhancement helping programmers writing
> exception safe code.

Bar speed reason from above, and more things to think of, true, that
would help. But we've been here already, didn't we ;-) ?

BTW, as you say, you'd like an optional compiler feature. I don't
think standard deals with such things - they define a language in
"shall" and "shall not" terms. So a compiler could do that, as a
quality of implementation enhancement, not the language (I could be
wrong). Due to perf penalty of throw(), I bet you your proposal would
end in some other mechanics, not "throw()". Perhaps some sort of a
compiler-specific feature (e.g. through __declspec).

Goran.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: DeMarcus on
>> So if the following holds:
>>
>> * A no-throw function can, without functional harm, be declared throw()
>> since such function must throw nothing, compared to a throw( MyException
>> ) that can throw more than just MyException due to templates.
>>
>
> If throw() is enforced during runtime - i.e. there is an implicit
> catch(...)+handler added to each such function - this can have
> performance implications depending on the platform.
>

Yes, however, for those who need the performance better than the
exception safety, they probably don't use throw() today anyway. And if
they do they have the performance implications already.

For those who do not use throw() today but wish to migrate to it, maybe
the compiler could optimize away the implicit catch(...)-handler if all
contents in the function is declared throw(). For throw()-declared
functions that use no-throw functions without throw() we will probably
never get rid of the implicit catch(...)-handler performance hit.


>> If that holds, then I claim an optional feature in the compiler can, by
>> means of static checking during compile-time, help finding no-throw
>> functions that throws anyway. This optional feature would be no
>> disadvantage, but only an enhancement helping programmers writing
>> exception safe code.
>>
>> Please give your comments on this.
>>
>
> I fully agree that some mechanism to statically enforce/analyse the
> no-throw guarantee would be very welcome!
>
>
> br,
> Martin
>

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Francis Glassborow on
Martin B. wrote:
> DeMarcus wrote:
>>> (....)
>>>
>>> BTW, don't you trust e.g. standard lib/booost implementors to do the
>>> right thing? 'cause they do, much more often than I. Their code is
>>> better than mine if nothing else because there's so many eyes on their
>>> code, and so little on mine ;-).
>>>
>>
>> I trust the boost implementors fully, I mean, it was one of the founders
>> of boost that published the idea of exception safety guarantees; the
>> technique I'm now working hard to conform to.
>>
>> Nevertheless, just because they're renowned C++ experts, that doesn't
>> stop me from proposing enhancements to their ideas.
>>
>> So if the following holds:
>>
>> * A no-throw function can, without functional harm, be declared throw()
>> since such function must throw nothing, compared to a throw( MyException
>> ) that can throw more than just MyException due to templates.
>>
>
> If throw() is enforced during runtime - i.e. there is an implicit
> catch(...)+handler added to each such function - this can have
> performance implications depending on the platform.
>
>> If that holds, then I claim an optional feature in the compiler can, by
>> means of static checking during compile-time, help finding no-throw
>> functions that throws anyway. This optional feature would be no
>> disadvantage, but only an enhancement helping programmers writing
>> exception safe code.
>>
>> Please give your comments on this.
>>
>
> I fully agree that some mechanism to statically enforce/analyse the
> no-throw guarantee would be very welcome!


And part ofg that mechanism will have to be a way to reassure the
compiler that a function call will not throw (or to put it another way,
if it does then the programmer takes full responsibility)

Just for the purposes of exposition:

int foo(int); // programmer has not declared foo
// not to throw

int bar() nothrow {
int i(nothrow foo(0)); // assures compiler that
// this call will not thorw
// more code
}

I think that some such mechanism is necessary to deal with the many
existing libraries where perfectly reasonable functions that will not
throw have not been declared as not throwing.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]