Getting use of pure virtual function error when trying to push unique_ptrs to a vector

c++ core guidelines pdf
c++ vector of derived classes
c++ vector of abstract class
vector of pointers c++
shared_ptr
make_unique
c++ vector of pointers to objects
c++ vector of superclass

So I have an abstract class, called MyClassParent, which MyClass inherits from. I run the following code:

        for(auto e:elements){
            MyClass m = *this;
            MyClass * mpointer = &m;
            if(mpointer->xLargerthanY(x,y)){
                    rv.push_back(unique_ptr<MyClassParent>(mpointer));
                    if(!rv[0]->solved()) cout<<"true";//works as expected
            }
        }
        rv[0]->solved();//gives pure virtual function called error

What's strange is that rv[0]->solved() inside the for each loop works as expected, returns true if the object has x greater than y. But if I call the function from outside the for each loop, I get a pure virtual function called error, which should never happen since I override solved() in the child class. I suspect this has something to do with the unique_ptr function, as my solved method makes no changes to the object and only return true of false.

I have tested this with many other methods, they all work inside the for each loop, but as soon as I exit it, I get the pure virtual function called error.

rv[0]->solved();//gives pure virtual function called error

Of course it does. Your program has undefined behavior, so it can do anything. It's also fairly easy to distill that snippet into what's causing the problem:

MyClass *ptr;
{
  MyClass m;
  ptr = &m;
}
ptr->solved();

Once we get rid of all of those red herrings, we see that all the pointers in your rv container point to objects with automatic storage durations, that have since gone out of scope. Using them to access that object is just going to behave in some undefined manner.

If you want to have rv store owning pointers to copies of this, then create those copies with dynamic storage duration

for(auto e:elements){
    MyClass& m = *this; // Assuming we need the reference binding
    if(m.xLargerthanY(x,y)){
        rv.push_back(make_unique<MyClass>(m)); 
    }
}

And now everything points at valid objects.

Error in pushing unique_ptrs from map into a vector, Getting use of pure virtual function error when trying to push unique_ptrs to a vector - c++. This requires a class containing the GetVectorOfResources to be though of as a Collection. And it makes sense as I think about it. Heres another thing then: What if one class returns a result of some processing as vector<unique_ptr<HeavyResource>> (it passes the ownership of the results to the caller), and it is supposed to be used for some subsequent processing: vector<unique_ptr

Ok, let's start with a little introduction because you seem to not have a grasp on some things needed to understand smart pointers:

Automatic storage duration: the lifetime of an object is managed by the compiler. Its lifetime is defined by the scope of the variable associated.

E.g.:

{
    X x; // lifetime of x starts here
    // ....

} // lifetime of x ends here

Dynamic storage duration: the lifetime of an object is managed by the programmer. It starts with a call to new and ends with a call to delete (this is simplified a bit).

E.g.:

auto foo(X* x)
{
    delete x; // lifetime ends with delete
}


{
    X* x = new X{}; // lifetime starts with new

    foo(x);
}

In C++ you should never explicitly call new / delete and use smart pointers instead.

unique_ptr (unless specified otherwise) on destruction will automatically call delete on the pointer it helds. This is the reason it must be provided with a pointer to a dynamic object i.e. allocated with new. This is one of your problems.

X x;

std::unique_ptr<X> p{&x};
// p receives a pointer to an automatic storage duration
// this is 100% wrong. The destructor for x would be called twice
// once as part of the automatic lifetime of x
// and then as part of the destructor of p
// resulting in UB

this is what you do here:

MyClass m = ...;
MyClass * mpointer = &m;
unique_ptr<MyClassParent>(mpointer);
// unique_ptr receives a pointer to an automatic storage duration object

As if that weren't enough the other problem you have is that you access a dangling pointer.

The scope of m is within the for. The vector holds pointers to such objects and those objects go out of scope after each iteration. When you do rv[0] you access an object whose lifetime has ended. Undefined behavior again.

I hope you have a better understanding of what unique_ptr does and what problem it solves. The solution is - as Storry Teller showed - to use make_unique.

What make_unique does: it calls new and creates an unique_ptr from that pointer returned by new. You could do this by hand yourself but you shouldn't because of other problems: Differences between std::make_unique and std::unique_ptr

A vector of pointers to different derived classes of the same base class, Error in pushing unique_ptrs from map into a vector and try to push each value to a std::vector , I see the following error to reference a deleted function CreateInstanceFromList c:\program files BaseInt is a BaseClass with an int member and a pure virtual replaceInt() . You could use std::shared_ptr . When you use std::vector<A> m_As;, the vector can only fit A objects. If you use pointers instead then polymorphism can work and call the correct printX function. However, this has the problem of dangling pointer if the lifetime of the pointed to object expires. To handle that it would be better to use a smart pointer class like std::unique_ptr.

As pointed by @StoryTeller this is undefined behavior, but let me explain why it behaves the way it does in this case. Since it is undefined behavior, there is no guarantee it will behave this way in different compilers or systems, but I will explain why there is a good chance it will:

    for(auto e:elements){
        MyClass m = *this;
        MyClass * mpointer = &m;
        if(mpointer->xLargerthanY(x,y)){
                rv.push_back(unique_ptr<MyClassParent>(mpointer));
                if(!rv[0]->solved()) cout<<"true";//works as expected
        }
    }
    rv[0]->solved();//gives pure virtual function called error

Here

    for(auto e:elements){
        MyClass m = *this;
        ....
    }

A pointer to m is stored into the rv vector. But when m exists scope, the object is being destroyed. The code implicitly calls MyClass::~MyClass(), which in the end replaces the virtual table of the object. First the derived class is being destroyed, and at the last step of this destruction the virtual table is replaced so that the object no has the virtual table of the base. In the base, solved() is pure virtual, so calling:

rv[0]->solved();

so calling this function finds the definition of the base, only. The derived object no longer exists, so it can't be used. In this case, in the base class, resolved() is pure virtual, and has no body. That's why it crashes the way it does. If you had a non-virtual resolved() in the base, then there is a good chance that you'd have a different crash, since the object had been destroyed already.

Note that even if this code did not crash, then later on, when rv is destroyed things become messy. The pointers inside rv point to the stack, but std::unique_ptr calls delete and assumes that the object is on the heap. Either that will crash immediately, since this is an illegal pointer, the heap/stack will be trashed, or it will be simply ignored. The exact behavior is unknown, since this is also undefined behavior.

Here is a simpler case when you'd get a similar problem:

class Base
{
    public:
            virtual ~Base() { bar(); }
            virtual void foo() = 0;
            void bar() { foo(); }
};
class Derived: public Base
{
    public:
            void foo() override { };
};
int main()
{
    Derived b;
}

C++ Core Guidelines, You can specify base class with virtual function Update and derived classes overriding this function. Here is simple example: class Enemy { public: // this is  Since the game updated, whenever I try the Shen mission, the game crashes when the last soldier makes up the elevator, and I am given this message: pure virtual function being called while application was running (gisrunning == 1) Been trying to figure it out. I have tried this with and without mods, verified cache, etc, but it still happens. Unless there is a fix out there somewhere, this is

Embind, The C++ Core Guidelines are a set of tried-and-true guidelines, rules, and However, we do believe that a program that uses a rule is less error-prone For example, we use plain vector rather than std::vector . class Shape { // better: Shape is a pure interface public: virtual Point center() const = 0; // pure virtual functions  A pure virtual function (or abstract function) in C++ is a virtual function for which we don’t have implementation, we only declare it. A pure virtual function is declared by assigning 0 in declaration.

[PDF] Guidelines for the use of the C++14 language in critical , Embind is used to bind C++ functions and classes to JavaScript, so that the embind has built-in support for return values of type std::unique_ptr . struct Array10 { int& get(size_t index) { return data[index]; } int data[10]; }; val Let's begin with a simple case: pure virtual functions that must be implemented in JavaScript. But before C++17, it’s not. Here are various alternatives you can use to approach this. Let’s see the motivating problem first. The case: transfering sets of unique_ptrs. We start by seeing what a std::set of std::unique_ptr would represent, and then we see what problem happens when trying to transfer the contents of one set to another.

unique_ptr and destructors and pure virtual : cpp_questions, parameters for a virtual function and all the functions that override it. See MISRA C++ Compliant - try keyword is a part of C++ Language Standard. 10. {. 11. One way to find a call to a pure virtual function is to replace the pure virtual function with an implementation that calls the Windows API function DebugBreak. When using the debugger, DebugBreak will cause a hard-coded breakpoint.

Comments
  • Hint: what is a unique_ptr for? What does it do that a raw pointer doesn't?
  • @juanchopanza I know its auto deleted when something falls out of scope, but I checked that rv[0] outside the for each loop still has the same memory address as rv[0] inside the for each loop. Also, know any fixes to this, I need to be able to called solved() outside the loop.
  • Two separate things are managing the lifespan of the same object. That never ends well.
  • MyClass m = *this; creates a copy of this object stored in a local variable, and MyClass * mpointer = &m; stores a pointer to such variable. Such object (m) gets destroyed at the end of the loop (even at the end of current loop iteration). Hence, dereferencing pointer to it, after the loop, is undefined behavior. I couldn't think of a proper way to fix this issue (due to lack of information, of what such code is expected to do), so I didn't write this as an answer.
  • If I do MyClass& m = *this; I get the error "binding const MyClass to reference of type MyClass& discards qualifiers"
  • @AlexSmith - So bind to a const reference.
  • Also I need to use c++11 for this which doesn't have make_unique(), so what's the equivalent of this?