C++ Logo

std-discussion

Advanced search

Accessing data members in constructors' function try bocks

From: Frank B. Brokken <f.b.brokken_at_[hidden]>
Date: Wed, 18 Jan 2023 17:02:41 +0100
Hi all,

Recently I noticed item #10 in section 14.4 (Handling an exception), n4917.pdf
(https://github.com/cplusplus/draft/releases/latest):

    10 Referring to any non-static member or base class of an object in the
       handler for a function-try-block of a constructor or destructor for
       that object results in undefined behavior.

Unfortunately, that item isn't elaborated, and somehow I find it
puzzling. Cleary, if a class has composed data members then the destructors of
those already constructed data members have been called when the execution
reaches the constructor's function-try-block handler.

But why would referring to members of basic data types like 'int' be
undefined? To make matters concrete, consider the following little program:

     1: #include <iostream>
     2:
     3: class Int
     4: {
     5: int d_value;
     6:
     7: public:
     8: Int(int value);
     9: };
    10:
    11: Int::Int(int value)
    12: try
    13: :
    14: d_value(value)
    15: {
    16: throw 0;
    17: }
    18: catch (...)
    19: {
    20: std::cerr << "value = " << d_value << '\n';
    21: }
    22:
    23: int main()
    24: try
    25: {
    26: Int ival{ 5 };
    27: }
    28: catch(...)
    29: {
    30: std::cerr << "done\n";
    31: }
    
The class is defined in lines 3 thru 9. It has merely an int data member. The
constructor (lines 11 thru 21) initializes its data member and then throws an
exception, caught by its handler, where d_value's value is
displayed. Eventually main's exception handler issues a smalll message.

What puzzles me is why the Int-constructor's handler's use of the object's
d_value data member would result in undefined behavior. To my understanding,
since function main's Int object is a local variable, it lives in main's stack
frame. So it ceases to exist once that stack frame is removed from the
stack. But that hasn't yet happened when Int's constructor throws, so unless
something magic's happening the Int object still exists by the time the
execution reaches the constructor's function-try-block handler.

I looked for answers to my puzzle in the
https://lists.isocpp.org/std-discussion/ archives, looking for things like
'exceptions thrown by constructors' but I didn't find a posting covering my
puzzle. Maybe I'm overlooking something trivial? In any case I'd appreciate
receiving some background info about section 14.4's item #10.

Thanks in advance,

-- 
    Frank B. Brokken
    (+31) 6 5353 2509
    PGP Key Fingerprint: DF32 13DE B156 7732 E65E  3B4D 7DB2 A8BE EAE4 D8AA

Received on 2023-01-18 16:02:46