Vinícius
Vinícius

Reputation: 15746

Can I re-use a pointer in this case?

Suppose:

struct Foo
{
    Obj* pObj;
    Foo() : pObj(NULL);
};

Obj* CreateObj()
{
   //do some stuff and then
   return new Obj; //obj is a class
}

int main()
{
   Foo foo;
   foo.pObj = CreateObj();
   DoSomeOperationWithTheObj( foo.pObj );
   //suppose foo is a monster that should be 'killed' or deleted now
   delete foo.pObj;
   foo.pObj = NULL;
   //the question is can this pointer be 're-used' now like this:
   foo.pObj = CreateObj(); //create another object
}

Since the pointer was deleted, isn't there a problem re-using it right?

Upvotes: 1

Views: 2959

Answers (6)

falero80s
falero80s

Reputation: 398

Yes you can reuse it. But there is one possible security implication in terms of memory safety. This is a very edge-case scenario. And this shouldn't be a concern for most apps. But you must know the limit from all sides when it comes to security and safety.

Suppose your application has been running since a long time, if it frequently keeps reusing the same memory address (pointer re-use) to bind a new object there is a chance that some malicious actor can inject arbitrary code/execution point onto that specific pointer address that will make your application execute their code instead of the original one that came with the application.

After you delete an object and set it to 'nullptr' and the re-create it again by calling new or any other fancy method, that new allocation will likely reside onto a different memory location than the address of the previous pointer variable (no guarantee though because it's OS's responsibility to do so (finding appropriate location for creating new object etc)).

Upvotes: 0

KillianDS
KillianDS

Reputation: 17176

As for your original question: yes, you can reassign to pointers like that. A pointer holds just a memory address and nothing more.

But you should not actually ever do this because handling raw pointers like this can lead to bugs, you already have a few of those in your code. Modern C++ allows you to do this way more nice and without concern. Suppose we start from this (compilable) code, i replaced Obj by an int, but the fact that it's a native type instead of a class does not matter:

#include <iostream>

struct Foo
{
    int* pObj;
    Foo() : pObj(NULL) {}
};

int* CreateObj()
{
   return new int(42); //obj is a class
}

int main()
{
   Foo foo;
   foo.pObj = CreateObj();
   std::cout << *foo.pObj << std::endl;
   delete foo.pObj;
   foo.pObj = new int(13);
   std::cout << *foo.pObj << std::endl;
   delete foo.pObj;
}

We can convert this to the following:

#include <iostream>
#include <memory>

struct Foo
{
    std::unique_ptr<int> pObj;
    Foo() : pObj(NULL) {}
};

std::unique_ptr<int> CreateObj()
{
   return std::unique_ptr<int>(new int(42));
}

int main()
{
   Foo foo;
   foo.pObj = CreateObj();
   std::cout << *foo.pObj << std::endl;
   foo.pObj = std::unique_ptr<int>(new int(13));
   std::cout << *foo.pObj << std::endl;
}

Note that the major change is that I removed raw pointers and replaced them with the unique_ptr wrapper. This has a few advantages:

  1. You clearly state ownership, a unique_ptr can only be owned by the current scope. While createObj creates the object, by returning the temporary (nameless) unique_ptr it releases ownership so the caller can delete it whenever it wants. This will avoid tricky memleaks.
  2. Deletes happen automatically for you, either when the unique_ptr goes out of scope or when it is overridden (e.g. by the assignment operator).

Upvotes: 3

Mark Garcia
Mark Garcia

Reputation: 17708

There is definitely no problem in doing that. Pointers are just containers of addresses (analogous to variables which contains values).

new allocates an object and returns an address to it. You can then just assign the result address to any pointer (of the proper type) you want, whether it may be deleted pointers, pointers holding "existing" allocated objects, NULL-holding pointers or uninitialized pointers.

Upvotes: 1

You can reuse the pointer because you never deleted the pointer; you deleted the Obj that the pointer was pointing to. Keep in mind that a pointer is storing a memory address. So, just like you can change an int to a different value, you can always change a pointer to remember, or point, to a different memory address. Also, when you perform the delete operation on foo.pObj, you are not saying "delete foo.pObj". Instead you are saying "delete the Obj that foo.pObj is pointing to".

Where a problem would arise is if you tried to do something to the object that foo.pObj is pointing to after you performed the delete operation.

Upvotes: 0

Eric Z
Eric Z

Reputation: 14505

There is no problem to reuse a pointer, as long as the memory previously allocated is deallocated first, as you already did in your code.

When you delete a pointer, you actually free the memory it points to. The value of the pointer(the starting address of that memory) is unchanged, until you reassign it by pointer = NULL or pointer = new ..

Upvotes: 0

Lyubomir Vasilev
Lyubomir Vasilev

Reputation: 3030

Yes, you can re-use the pointer. A pointer is just a way to refer to an object. Since you delete the object, you are free to use the pointer for whatever you need it.

Upvotes: 1

Related Questions