Re: Using noexcept
I personally wanted UB to push such bug handling under QOI but it
seems that the committee though that UB for such unhandled exceptions
is somewhat bad PR for a language.
This sounds like a strange argument to me. Actually, there is lots of UB
already in C++ as it is right now, and it has ever been this way - if
the user does something stupid, well,...
Bug mitigation actually became popular in some environments due to
security concerns related to poorly written code and made such
"trendy" despite of the perf overhead.
For example: MSVC compiler supports stack corruption mitigation (AKA /
GS option), Win32 heap also has such, some MSVC CRT APIs has "secure"
version of memcpy and STL vendors provides "secure" mode (e.g. check
for bad iterators).
Note that noexcept violation is always a bug and on such the program
is anyway under the UB umbrella...
OTOH, being a QOI, the above bug handling mitigation can be enabled/
disabled by the user.
For example, we must use /GS but not secure STL. I don't expect safe
heaps tight embedded systems.
I'm not sure what makes unhandled exceptions more appealing for
standard mitigation especially when even the conservative win32 envs
are using compiler that never cared about such...
Note that unhandled-exceptions are among the most common bugs in
"throwing C++" and given aggressive "no unwind" optimization and
masking catches can lead to bugs like deadlocks (e.g. lock is not
released yet the unhandled exception was masked).
IOW, you get less optimal code by adding "noexcept" -
This is not true. The compiler can avoid generating unwind code for
the throwing case which is the main no-throw optimization (caller and
callee).
Ok, I see what you mean, but I don't quite agree with the argument.
Allow me to elaborate: Without a throw specification, the compiler has
to generate the unwind code, but this is usually "for free" since it is
not the common call path. Gcc generates rather a table in the binary
which code to call if stack unwinding is required.
Even with the unwind table approach (also done by x64-VC/win64) there
is still something that gets generated.
Now think generating such code for every operator-delete call site.
And then for destructors.
Such is expensive and for practically nothing.
I hope that compilers will be smart enough to avoid the noexcept EH
code for calls like delete.
Such also shows that UB is better since it allows more sophisticated
noexcept violation handling (e.g. avoid some for speedup).
Whereas if it would have been UB to throw an exception in noexcept, the
compiler would have to do nothing *at all* to handle such a case, and
thus there would be no code at all - hence no unwind code, and no
exception checking code.
Indeed. The compiler has more freedom to balance between safety and
performance with UB.
OTOH, compiler vendors are promising very low overhead safety...
so in which sense is this an improvement?
The nexcept(condition) is important for no-throw based user
optimization (e.g. move if no-throw).
That was the initial motivation as I understand. Well, maybe. Time will
show.
The aggressive vector like move optimization potential is there but I
agree with you about whether it will actually matter.
I would also have understood if noexcept would be statically checked
since then I had means to validate at compile time
Static validation is problematic in general due to conditional no-
throw functions (runtime).
For example:
vector<int> v(10); // reserve space for 10 elements
v.push_back(1); // no-throw since no allocation needed
map<int, int> m;
m[0] = 0;
m[0] = 1; // no-throw on replace
It seems that for static checking, noexcept needs to have another
flavor - "unconditionally might throw".
I don't think the compiler could be expected to prove in such cases that
the calls cannot throw. Actually, if I would have the *requirement* to
write a function that cannot throw, for whatever reason, I wouldn't use
the corresponding standard library functions, but rather build something
on my own.
The callers actually mainly wants to preallocate in order to avoid
perf impact in critical paths (e.g. insert under locks). why not use
vector::reserve that was invented to allow such and now has all the
move magic?
You might also fine may if(map[key]) checks in non-throwing contexts
(such can in general throw since it inserts on not found).
This is probably much more common than conditional no-throw, For
example:
void* operator new(size_t) noexcept(--);
void foo() noexcept
{
new A; // can be statically rejected
}
I don't understand? void *operator new(size_t) is definitely not
"noexcept" if the allocation fails.
Sorry for not being clear. I was using the imaginary noexcept(--)
syntax to mark function as "unconditionally might throw" since
noexcept(false) actually says that the function is allowed to be no-
throw hence disallowing static checking.
Why isn't that a warning either? Because it breaks the contract. In the
same vain, throwing an exception in noexcept breaks the contract, and
hence should be an error. Hence, everything that *potentially* may throw
cannot be used in noexcept -
This might be worthy to consider for new language but with C++ you
have much legacy code to consider and such makes your static check
impractical. OTOH, my suggestion for having another explicit notion
that says "not allowed from noexcept" seems less breaking (yet too
late for C++1x).
Note that I only talk about static checks for "unconditionally might
throw anything" and not the Java-like verbose/fragile exception
specifications that are statically checked.
I don't quite understand? Current code doesn't use noexcept, thus there
shouldn't be a problem?
As I said, I meant that functions like throwing operator-new should be
annotated to say "disallowed from noexcept" as it's done by some
compilers for explicit "throw" call from throw().
I think that static checking is nice to have but not super crucial
since anyway proper testing is needed given the many other bugs that
can be detected only at runtime or using custom static analysis tools
(e.g. all the traditional UB bugs).
Again, this sounds like a strange argument to me. I would prefer to
fixup the language - "just because we've been sloppy in the past, let's
continue to be sloppy". (-; No, I don't think so.
I think that language designers tries to be careful with having
potentially polluting notations in the language despite of the good
intentions. Exception specifications is a prime example for such.
OTOH, I wonder what Prof. Stroustrup will think about having explicit
notion to disallow throwing calls from no-except (e.g. throw(true) for
throwing operator-new) ;-).
Thanks,
Rani
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]