2

In C++, if a method may throw only because the invariants of the class are not maintained, should I mark it noexcept?

For example, a list have a pointer to the link, which should be either nullptr or correct pointer, and a method dereferences this pointer. Does it prevent using noexcept?

statnik
  • 61
  • 4
  • Possible UB doesn't prevent use of `noexcept`. – Cheers and hth. - Alf Feb 26 '15 at 10:44
  • 1
    Dereferencing an invalid pointer is undefined and does not cause a C++ exception. – molbdnilo Feb 26 '15 at 10:49
  • @molbdnilo Since it's undefined, it _might_ cause a C++ exception. Then again, it might not; it might just corrupt the free space arena, so your program crashes in some totally unrelated place. (Visual Studios has an option to convert accessing outside of mapped memory into an exception. But of course, an invalid pointer won't necessarily point outside of mapped memory. So you can't write code which depends on this exception. And in most cases, you'll want to abort, rather than throw an exception anyway.) – James Kanze Feb 26 '15 at 11:36

3 Answers3

1

If a function can exit via an exception, you should not mark it nothrow; nothrow is a guarantee that it never exits via an exception. It is essential that there be at least a few functions which never throw (and I mean never) if you want to write exception safe code.

If the class invariants cannot be maintained, you shouldn't throw an exception; all you can reasonanbly do is abort the process. Don't confuse this with a constructor which cannot establish the invariants, however; its fine to throw then, since there will be no object afterwards which doesn't conform to the invariants. Also, in certain cases, it's valid to define a weaker set of invariants that hold after throwing. Say just enough to guarantee that the object can safely be destructed. This depends on the application (and how the design handles exceptions). But such functions cannot be declared nothrow.

With regards to your concrete example: if the invariant is either a correct pointer or a null pointer, there's no way to test this and get an exception anyway. If the pointer is invalid (doesn't point to a valid object of the type, and isn't null), then you have undefined behavior. Anything can happen, and on real systems, anything does happen if you dereference the pointer.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
0

If a function is throwing an exception to report any problem, then it should not be declared noexcept. It would be violating, in effect, the contract it promises to satisfy.

Whether it throws an exception or not, it is also good practice that the object maintain its invariant. The usual practice is that all constructors establish an invariant and all other member functions maintain that invariant, until the object is destroyed (and destructor invoked).

If a function dereferences a nullptr, its behaviour is undefined. It is not required to throw an exception.

Rob
  • 1,966
  • 9
  • 13
0

If a method can throw an exception when dereferencing a null pointer, it should not be marked noexcept. If you really want it to be noexcept, you should test the pointer to null (and return a special value) before dereferencing it. For example

if (pt == NULL) return NULL;
// do use *pt or pt->xxx
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • 1
    The function checks that the pointer is not null and dereferences it. And the invariant is that the pointer is either null or correct. Then if it is not correct, it is undfined behaviour? So it throws only because of UB, and may be marked onexcept? – statnik Feb 26 '15 at 10:48
  • @statnik I probably doesn't throw at all. It's impossible (or almost) to determine whether a pointer is valid or not; if you write through an invalid pointer, the most common result is that some other object will be corrupted, or that you'll corrupt the free space arena. Both of which are likely to cause the program to crash some time later, in totally unrelated code. – James Kanze Feb 26 '15 at 11:38