IBM Support

LI80776: DESTRUCTOR IS NOT BEING CALLED WITH RETURN IN TRY BLOCK

Subscribe to this APAR

By subscribing, you receive periodic emails alerting you to the status of the APAR, along with a link to the fix after it becomes available. You can track this item individually or track all items by product.

Notify me when this APAR changes.

Notify me when an APAR for this component changes.

APAR status

  • Closed as program error.

Error description

  • If a return is used in a nested try block, then the destructors
    of objects are on the stack will not be called. This is shown
    with the testcase below:
    
    ===== COMPILE COMMAND:
    xlclang++ test.cpp
    
    ===== TESTCASE:
    $ cat test.cpp
    #include <iostream>
    
    using namespace std;
    class Line {
       public:
          void setLength( double len );
          double getLength( void );
          Line();   // This is the constructor declaration
          ~Line();  // This is the destructor: declaration
    
       private:
          double length;
    };
    
    // Member functions definitions including constructor
    Line::Line(void) {
       cout << "Object is being created" << endl;
    }
    Line::~Line(void) {
       cout << "Object is being deleted" << endl;
    }
    void Line::setLength( double len ) {
       length = len;
    }
    double Line::getLength( void ) {
       return length;
    }
    
    
    void  try_1()
    {
       Line line1;
       try {
               line1.setLength(96.0);
           return;}
           catch ( ... ) {
           cerr << "Catch 2"; }
    }
    void  try_nested()
    {
       Line line1;
       {
         {
           try {
               line1.setLength(96.0);
           return;}
           catch ( ... ) {
               cerr << "Catch 2";
           }
         }
       }
    }
    
    
    void  try_try()
    {
       Line line2;
       try {
               line2.setLength(96.0);
            try {
    
               line2.setLength(196.0);
    //           line2.~Line();
                return;
                   }
           catch ( ... ) {
           cerr << "Catch 1" ;}
           }
           catch ( ... ) {
           cerr << "Catch 2"; }
    
    
    }
    
    
    // Main function for the program
    int main() {
    
       cout << "               " <<endl;
       cout << "               " <<endl;
       cout << " BEGIN: single try with return" <<endl;
       cout << "-------->  Expectartion: Constructor/Destructor is
    called " <<endl;
    
       try_1();
       cout << " END:   single try with return" <<endl;
    ////////////
       cout << "             --------   " <<endl;
       cout << "               " <<endl;
       cout << "               " <<endl;
       cout << " BEGIN: nested  try with return" <<endl;
       cout << "-------->  Expectartion: Constructor/Destructor is
    called " <<endl;
    
       try_nested();
    
       cout << " END:   nested try with return" <<endl;
    ///////////
       cout << "               " <<endl;
       cout << "               " <<endl;
       cout << " BEGIN: try in a try with return" <<endl;
       cout << "-------->  Expectartion: Constructor/Destructor is
    called " <<endl;
    
       try_try();
    
       cout << " END:  try in a try with return" <<endl;
       // cout << "Length of line : " << line.getLength()+1 <<endl;
       return 0;
    }
    
    
    $
    
    
    ===== ACTUAL OUTPUT:
    $ ./a.out
    
    
    BEGIN: single try with return
    -------->  Expectartion: Constructor/Destructor is called
    Object is being created
    Object is being deleted
    END:   single try with return
                 --------
    
    
    BEGIN: nested  try with return
    -------->  Expectartion: Constructor/Destructor is called
    Object is being created
    END:   nested try with return
    
    
    BEGIN: try in a try with return
    -------->  Expectartion: Constructor/Destructor is called
    Object is being created
    END:  try in a try with return
    $
    
    ===== EXPECTED OUTPUT:
    $ ./a.out
    
    
    BEGIN: single try with return
    -------->  Expectartion: Constructor/Destructor is called
    Object is being created
    Object is being deleted
    END:   single try with return
                 --------
    
    
    BEGIN: nested  try with return
    -------->  Expectartion: Constructor/Destructor is called
    Object is being created
    Object is being deleted
    END:   nested try with return
    
    
    BEGIN: try in a try with return
    -------->  Expectartion: Constructor/Destructor is called
    Object is being created
    Object is being deleted
    END:  try in a try with return
    $
    

Local fix

  • N/A
    

Problem summary

  • USERS AFFECTED:
    Users who have return statements within try-catch blocks may be
    affected by this issue.
    
    PROBLEM DESCRIPTION:
    The C++ runtime exception handling was not correctly
    processing/cleaning the exceptions when try-catches contained
    return statements.
    

Problem conclusion

  • We are now correctly walking the enclosing try/catch blocks of
    the return and emitting the correct actions before the return.
    

Temporary fix

Comments

APAR Information

  • APAR number

    LI80776

  • Reported component name

    XL C/C++ LINUX

  • Reported component ID

    5725C7310

  • Reported release

    G11

  • Status

    CLOSED PER

  • PE

    NoPE

  • HIPER

    NoHIPER

  • Special Attention

    NoSpecatt / Xsystem

  • Submitted date

    2019-04-17

  • Closed date

    2019-04-18

  • Last modified date

    2019-04-18

  • APAR is sysrouted FROM one or more of the following:

    IJ15509

  • APAR is sysrouted TO one or more of the following:

Fix information

  • Fixed component name

    XL C/C++ LINUX

  • Fixed component ID

    5725C7310

Applicable component levels



Document information

More support for: XL C/C++ for Linux

Software version: G11

Reference #: LI80776

Modified date: 18 April 2019