From: ThosRTanner on
On Feb 11, 1:16 am, "Nevin :-] Liber" <ne...(a)eviloverlord.com> wrote:
> In article
> <82be602f-bb4e-45af-a04e-fcbeee7fd...(a)z17g2000yqh.googlegroups.com>,
> ThosRTanner <ttann...(a)bloomberg.net> wrote:
>
> > That function *might* throw because the constructor for
> > std::vector<int> isn't declared throw().
>
> > A function won't throw if and only if the only functions it calls
> > doesn't throw (and it doesn't throw itself of course). What you can
> > never tell is if it it will throw but I don't think that's important.
>
> > It is trivially easy to statically analyse whether or not a function
> > might throw. You can even tell precisely what it might throw.
>
> Not without whole program analysis.

No. It is trivial. What a function can throw is the union of the
exception specifications of all the functions it calls, and all the
throws it executes. A function without an exception specification can
throw anything. An extern "C" function should throw nothing as it
breaks the contract of being callable by C if it does that.

> For instance, how can you tell if the function qsort throws? You have
> to analyze the compare function, which might be determined at run time.
> Worse, what happens if that compare function calls a global function
> stored in a tr1::function?

The qsort function can't throw because it is a C function, and
anything you pass to it should be an extern "C" function and extern
"C" functions can't throw (because C can't cope with it)

>
> If the poster is really asking for a compiler extension, I'm not sure
> why he is posting it here instead of asking his compiler vendor (along
> with how much he is willing to contribute or pay to make it happen).

Well, yes. Either that or a standards change, because if he wants all
compilers to issue a diagnostic, that is a change to the standard

>
> Personally, I don't see much traction on this, as most folks just aren't
> seeing these kinds of issues very frequently (if at all) when using
> exceptions in day to day usage.
>
Well, in my case, as I've said before, we don't use exception
specifications at all, because throwing an exception that isn't
permitted by a callers exception specification causes your program to
terminate, and that is not acceptable for our software. And I doubt
we're the only people who have that requirement.


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

From: Seungbeom Kim on
DeMarcus wrote:
>
> I bought the book Exceptional C++ by Herb Sutter. It's an excellent
> book, buy it. However, even Sutter himself seems to be totally paralyzed
> when it comes to exception specifications, as I found when I
> surprisingly read the following.
>
> "Writing throw() limits you in the future in case you want to change the
> underlying implementation to a form that could throw.", page 54.
>
> Now, anyone in this community, raise a hand if you would be happy if one
> of your programmers or colleagues suddenly started to throw from a
> no-throw function. It's a silent and efficient way to put a company in
> Chapter 11.

Only if you relied on the fact that the function did not throw.
And you don't usually want to do that except for a few specific
functions advertised and well-known as non-throwing, such as
destructors, pop_back(), erase(), swap(), and so on. And some of
them (especially templates) depend on other functions not throwing,
so throw() can not be applied uniformly.

So, the general rule is to assume that most functions can throw,
and program defensively. Fortunately, with proper techniques such
as RAII, the additional burden can be made minimal.

--
Seungbeom Kim

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

From: Andreas Wallner on
A few posts ago you described how you would use your proposed warning
for your own code. You would have to sort out a huge mass of warnings
related to librarys using exception specifications. You could not run
those compilations as part of a regression test. I think that you
would most likely overlook some issues although you checked for
issued, just because of the huge amount of repetitive work the
programmer checking the compiler output would have to do.


>void f() throw()
>{
> try { myVector.pop_back(); } catch(...) {}
>}

That could for, but what if you accidentially wrap something in such a
try-catch block that is not-nothrow? I would consider it really bad if
that happened...

Also I wouldn't use throw() because of the additional code that is
generated and does not help me in any way.

>That is why I proposed it as an optional feature so that it won't affect
>nobody except those who see it as a help. As for me, until this no-throw
>issue has gotten a clean solution, I prefer this clutter code to a core
>dump.

If you are sure that the function you wrapped with your try-catch
block is really nothrow, you would never have to fear a core dump. If
you are not sure that the function is nothrow then you would swallow
the thrown exception, and have ignored it... I would feel better with
an application that catches this exception at an much higher level,
then just swallow the exception and never have a clue that it was
thrown.

I think such a warning would introduce more problems then it would
solve. You would write code that has no functional use, that is only
there to be able to do checks with that specific compiler warning (you
would anyway have to check by hand).

>Now, anyone in this community, raise a hand if you would be happy if one
>of your programmers or colleagues suddenly started to throw from a
>no-throw function. It's a silent and efficient way to put a company in
>Chapter 11.

It would be better to say that you should only use throw() (if you use
it at all) if you had to, but not if you could (depending on the
current implementation).

I think that solid test cases for your own stuff, as well as code
reviews would be a better approach to this problem. Or try to write a
static code analysis tool that can do this, like some others already
suggested. But without parsing library code as well such a tool might
not be usable at all. (Because of the above mentioned problems)

--
[ 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 11, 2:17 am, DeMarcus <use_my_alias_h...(a)hotmail.com> wrote:
> "Writing throw() limits you in the future in case you want to change the
> underlying implementation to a form that could throw.", page 54.
>
> Now, anyone in this community, raise a hand if you would be happy if one
> of your programmers or colleagues suddenly started to throw from a
> no-throw function. It's a silent and efficient way to put a company in
> Chapter 11.

I think that you misunderstood this, and I think that's because you
fail (or refuse?) to accept what throw() does. By writing throw(), I
am NOT saying "this does not throw". I am saying "if this throws, I
die". That's a BIG difference.

So your argument is a poor way to turn things around. Because, with
throw(), if thing throws, you die. Without throw() (and surrounding
code is not exception-safe), you have a serious bug. Either way, you
have a bug. But former case, with throw(), is actually much more
drastic - you die right away.

So if absence of throw() in an otherwise no-throw function puts
company in Chapter 11, then it's presence can only put it there
faster.

Goran.


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

From: Jeff Schwab on
Francis Glassborow wrote:
> DeMarcus wrote:
>>>
>>> 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.
>>>
>>>
>>
>> Yes, you're right, but to make it simple, i.e. keep the fingers away
>> from the standard, we can solve it like this for now.
>>
>> int foo(int); // programmer has not declared foo
>> // not to throw
>>
>> int bar() throw() {
>> try {
>> int i(foo(0));
>> }
>> catch(...) {} // assures compiler that
>> // this call will not thorw
>> // more code
>> }
>
> But that is exactly the kind of added complexity that I do not want to
> clutter my code with.

It shouldn't be hard to wrap in a library, especially with the new
support for type inference.

namespace {

template<typename F>
class nothrow
{
F m_f;
public:

typedef typename F::argument_type argument_type;
typedef typename F::result_type result_type;

nothrow( F const& f )
: m_f( f ) { }

result_type operator()(argument_type const& a) throw() try {
return m_f(a);
} catch (...) {
return result_type( );
}
};

template<typename F>
nothrow<F> make_nothrow(F const& f) {
return nothrow<F>( f );
}

int foo(int) {
throw 42;
}
}

#include <functional>
#include <iostream>

int main() {
try { std::clog << "foo returned " << foo(42) << '\n'; }
catch (...) { std::clog << "foo threw\n"; }
auto bar = make_nothrow(std::ptr_fun(foo));
std::clog << "bar returned " << bar(42) << '\n';
}

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