Question

I get a runtime error when I execute the below code:

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Test
{
public:
    int value;
    Test( )
    {
        value = 1;
    }

    ~Test( )
    {

    }
};

int main() {
    shared_ptr<Test> pTest =  shared_ptr<Test>( new Test( ) );
    std::vector<weak_ptr<Test>> testList;

    testList.push_back( weak_ptr<Test>(pTest) );
    cout << "\n Before Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
        try
        {
            auto p = testList[i].lock();
            cout << "\n Item not null: " << p->value;
        }
        catch (bad_weak_ptr b)
        {
            wcout << L"Null object" << endl;
        }
    }

    pTest.reset( );

    cout << "\n After Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
        try
        {
            auto p = testList[i].lock();
            cout << "\n Item not null: " << p->value;
        }
        catch (bad_weak_ptr b)
        {
            wcout << L"Null object" << endl;
        }
    }

    // your code goes here
    return 0;
}

I was trying to find whether the pointer is still accessible (shouldn't be) after deleting the original shared pointer.

Was it helpful?

Solution

Lock doesn't check for null, it promotes a weak_ptr to a shared pointer. It doesn't throw when the object is deleted, but rather returns null.

This is what you should be doing.

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Test
{
public:
    int value;
    Test( )
    {
        value = 1;
    }

    ~Test( )
    {

    }
};

int main() {
    shared_ptr<Test> pTest =  shared_ptr<Test>( new Test( ) );
    std::vector<weak_ptr<Test>> testList;

    testList.push_back( weak_ptr<Test>(pTest) );
    cout << "\n Before Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
      auto p = testList[i].lock();
        if (p)
        {

            cout << "\n Item not null: " << p->value;
        }
        else
        {
            wcout << L"Null object" << endl;
        }
    }

    pTest.reset( );

    cout << "\n After Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
      auto p = testList[i].lock();
        if (p)
        {

            cout << "\n Item not null: " << p->value;
        }
        else
        {
            wcout << L"Null object" << endl;
        }
    }

    // your code goes here
    return 0;
}

To clarify, what happens when you to test_list>lock after pTest is reset is you get a shared_ptr which contains NULL. and ((Test*)NULL)->value is what happen when you do p->value, which is an obvious segfault.

The whole point of having a weak_ptr is to allow users the ability to safely get a reference to an object that may go out of scope. Exceptions would be a poor mechanism for this because exceptions are SLOW, and it is not necessarily a fatal error if the weak_ptr's parent goes out of scope. So the mechanism is lock either returns a new counted reference when promoted, or NULL if it can no longer promote the ownership level (the parent has expired).

OTHER TIPS

You could read the documentation instead of making assumptions about how things work.

lock does not signal nullpointer by throwing an exception: it returns a nullpointer.

So,

        auto p = testList[i].lock();
        if( p != nullptr )
        {
            cout << "\n Item not null: " << p->value;
        }
        else
        {
            cout << "\n Item is null." << endl;
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top