code_fodder
code_fodder

Reputation: 16331

std::unique_ptr dereference exception not catch-ed in try-catch block

So lets say I have:

struct test {
    bool a;
    int b;
};

int main()
{
    std::unique_ptr<test> ptr;
    // don't init the ptr

    try
    {
        if (!ptr->a)
        {
            std::cout << "ok" << std::endl;
        }
    }
    catch (const std::exception &ex)
    {
        std::cout << "ex: " << ex.what() << std::endl;
    }

    return 1;
}

So here I setup a unique pointer, but I don't init it (to simulate this in a larger code base) but I want to catch the exception.

The problem is that my exception is not called - I just get a crash (memory access fault)

I read a few similar questions (but not quite the same) that suggested that I pass the exception by reference - but this did not work.

So is it possible to catch a unique_ptr de-reference exception?

EDIT: I should add that this is on Windows 7 box running MSVS2012 executable - incase it is relevant!

Upvotes: 0

Views: 758

Answers (1)

Useless
Useless

Reputation: 67723

So is it possible to catch a unique_ptr de-reference exception?

There is no unique_ptr dereference exception to catch.

As the documentation says,

The behavior is undefined if get() == nullptr

You can easily write your own smart pointer with this Java-like behaviour, but it does mean paying for a test-and-branch on every dereference, which in general seems silly.

For the slightly different problem described in comments:

I have a list of unique_ptr's - I was trying to avoid individually checking each one by putting a try block around it.

the sane solution is probably to check it once and not on every subsequent dereference:

if(any_of(begin(ptrs), end(ptrs), logical_not<unique_ptr<test>>{})
{
  throw MyNullPointerException();
}

Per subsequent comments, you could just add a check-and-throw wrapper to your constructing function.

In C++17 you can almost get what you want by instead returning an optional<unique_ptr<test>> (ie, it either contains a populated unique_ptr, or nothing at all: in that case, calling value to extract the unique_ptr would throw std::bad_optional_access if there isn't really one there).

If you can import ot (or don't have C++17), the GSL is probably even better with gsl::not_null<T>. For example, you could instead store these things in your container

using unique_not_null = std::unique_ptr<gsl::not_null<test>>;

Upvotes: 4

Related Questions