Class Liberation Prevention

I need to pass a pointer to a class, so some code that I do not control. This code automatically releases () s pointer when this is done, but I need a class later. I was hoping that I could just create a wrapper class that would not allow the class to be freed without actually preventing the code from accessing it, but virtual calls do not work.

template <class T> class PointerWrapper:public T { public: T* p; PointerWrapper(T *ptr) { p=ptr; } ~PointerWrapper(void) { } T* operator->() const { return p; } T& operator*() const { return *p; } }; void codeIDontControl(Example *ex) { ex->virtualfunction(); delete ex; } void myCode() { Example *ex=new Example(); codeIDontControl(ex); do something with ex //doesn't work because ex has been freed codeIDontControl(new PointerWrapper<Example>(ex)); do something with ex //ex hasn't been freed, but the changes made to it via // Example::virtualfunction() in codeIDontControl() aren't there anymore } 

Basically, ex-> virtualfunction () calls a virtual function in PointerWrapper itself instead of a virtual function in PointerWrapper-> p. It seems like it is ignoring the β†’ operator?

Now I don’t need to use the PointerWrapper-esque class if there is another way to do this, but that’s all I could think of ...

I can't change the example either, but I can subclass it

+4
source share
3 answers

You should provide a Forwarder class that redirects virtual calls to a stored pointer. Releasing a freight forwarder class will not result in a free pointer. This approach does NOT need to make a copy (which can be costly / may not be implemented or even makes no sense):

 struct Forwarder : Example { Example *impl; Forwarder(Example *i) : impl(i) {} void virtualfunction() { impl->virtualfunction(); } }; 

Full code:

live demo :

 #include <iostream> #include <ostream> using namespace std; struct Example { virtual void virtualfunction()=0; virtual ~Example() {} }; struct Implmenetation : Example { bool alive; Implmenetation() : alive(true) {} void virtualfunction() { cout << "Implmenetation::virtualfunction alive=" << alive << endl; } ~Implmenetation() { alive=false; cout << "Implmenetation::~Implmenetation" << endl; } }; struct Forwarder : Example { Example *impl; Forwarder(Example *i) : impl(i) {} void virtualfunction() { impl->virtualfunction(); } }; void codeIDontControl(Example *ex) { ex->virtualfunction(); delete ex; } void myCode() { Implmenetation impl; codeIDontControl(new Forwarder(&impl)); //do something with ex //doesn't work because ex has been freed impl.virtualfunction(); } int main() { myCode(); } 

Output:

 Implmenetation::virtualfunction alive=1 Implmenetation::virtualfunction alive=1 Implmenetation::~Implmenetation 
+4
source

This is a bad design, really. Only the allocator is allowed to free memory. Such functions are dangerous because they go off with dangling pointers.

It's just on my head, maybe you could try something like this? This is not a safe idea, but if someone implemented it, I would be interested to know what will happen.

 class Foo { Foo(Foo* copy) : m_copy(copy) {} ~Foo() { if(m_copy) { *m_copy = *this; } } // Use copy constructor to create copy on destuction. Foo* m_copy; } Foo copy(NULL); Foo* original = new Foo(&copy); MethodThatDeletes(original); // Original should be destroyed, and made a copy in the process. original = NULL; // Copy should be a copy of the original at it last know state. copy; 
+3
source

You provide an example * for codeIDontControl. The overloaded operator-> in PointerWrapper is for the type PointerWrapper, and not for the type Example * or even for the type PointerWrapper * (i.e. for a value or reference of this type, and not for a pointer to this type).

Since the function you need to call is not controlled by you, you need to provide a complete wrapper of the type that it expects as a wrapper over the instance that you want to control the lifetime.

0
source

Source: https://habr.com/ru/post/1445282/


All Articles