1

I'm having difficulties trying to find a solution that will allow me to keep the scope of an object local to a main method while catching a potential initialisation exception.

The pseudocode below tries to best illustrate my problem.

int main () {
    // Initialisation
    SomeObject * object;

    try {
         SomeObject obj; // Initialisation can cause an exception
         object = &obj;
    }
    catch (SomeException &ex) {
         // Handle exception
    }

    // object out of scope undefined behaviour

    // Application Logic
    return 0;
}

I understand that the object will be deleted once the try block ends and so the pointer when used will lead to undefined behaviour.

How can I do something like this and pass the object to the function scope so the object is not deleted?

I can use a c++14 solution in my project.

a_dizzle
  • 43
  • 7
  • `to keep the scope of an object local to a main method` - why in this case and not declare it in scope where you want use it ? if you declare object as local variable in sub-function - it any way will be trash after you exit from this sub-function to `main`. so if you need have object in `main` scope - declare it here – RbMm May 28 '17 at 00:41
  • See also: https://stackoverflow.com/questions/24575896/catching-exceptions-from-a-constructor-means-that-my-instance-is-out-of-scope-af – M.M Aug 02 '18 at 12:19

2 Answers2

2

How can I do something like this and pass the object to the function scope so the object is not deleted?

You can use a smart pointer instead:

int main () {
    // Initialisation
    std::unique_ptr<SomeObject> object;

    try {
         object = std::make_unique<SomeObject>(); // Initialisation can cause an exception
    }
    catch (SomeException &ex) {
         // Handle exception
    }

    if(object) {
        // Application Logic
    }
    return 0;
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

The obvious way would be the "function try block"

int main() try
{
     SomeObject object;

     // Application logic - able to use object

     return 0;
}
catch (SomeException &ex)
{
     // Handle exception
}

This allows the exception handler to clean up before program termination.

If you want the exception handler within main(), then one option is

 int main()
 {
      try
      {
           SomeObject object;

            // Application logic able to use object
      }     
      catch (SomeException &ex)
      {
           // Handle exception
      }
}

With appropriate control structures (e.g. the entire try/catch within a loop) it is possible for the catch block to recover from the error, and recommence.

If you really want the definition of the object and the initialisation to be separate, you can do something like (C++11 and later);

#include <memory>
int main ()
{
    std::unique_ptr<SomeObject> object;

     try
     {
          object = std::make_unique<SomeObject>();
     }
     catch (SomeException &ex)
     {
         // Handle exception
     }

     // code here cannot assume construction of object succeeded

     if (object)
     {
         // Application Logic can assume object is properly constructed
     }
    return 0;
}

Before C++11, the above can use std::auto_ptr (which was deprecated in C++11 in favour of unique_ptr.

The suitable choice depends on whether you want the "Application logic" to be able to assume object has been properly constructed (i.e. the application logic is never executed until object construction succeeds) or if it must test for the possibility of failure.

Peter
  • 35,646
  • 4
  • 32
  • 74