2

Assume I have a pointer void* p, then after some passing in and out of functions, let's say p is now pointing to int. Then do I need to manually delete as delete static_cast<int*>(p)?

In most places people say delete only happen when there is new. But in this case, it's not but does C++ itself remember to release that memory?

Billadsf
  • 51
  • 1
  • 5
  • 9
    You only `delete` what you `new`. That always holds!! Stuff with automatic memory will have its memory handled automatically irrelevant of what you cast it to. – DeiDei Jun 13 '18 at 17:11
  • If you don't know where an allocation came from check the documentation for whatever provided it. It may be managed for you and it may require you to call a API function to free it. – user4581301 Jun 13 '18 at 17:14
  • Not all memory in C++ has to be released, both primitive types and objects may be somewhere on the stack, or in the global data section. Having a pointer to something does not mean it needs to be freed. – kamikaze Jun 13 '18 at 17:14
  • I'm worried that this question may encourage bad habits. A `void*` is rather unusual in C++. Putting that `void*` in charge of the lifetime of an object is almost certainly a design mistake. – Drew Dormann Jun 13 '18 at 17:28
  • 'Assume I have a pointer void* p' There is literally no need for a void* in modern c++; it's a hack to do things that weren't possible in C, which got carried over, but in all modern c++ code, even if it interacts with C, shouldn't use them. Your assumption is rejected ;) – UKMonkey Jun 13 '18 at 18:31
  • @DrewDormann Now we have Modern C++ and smart pointers calling `new` and `delete` is (usually) a bad habit! – Frank Boyne Jun 13 '18 at 18:32
  • @UKMonkey: Win32 programming frequently uses `void *`. Legacy code is everywhere. – jonspaceharper Jun 13 '18 at 21:36

2 Answers2

6

That all depends on how the int you're pointing to was allocated, you only delete what you new.


Correct (the int is new'd):

int* a = new int;
void* p = a;

//somewhere later...

delete static_cast<int*>(p);

Bad (the int is automatically managed):

int a = 0;
void* p = &a;

//somewhere later...

delete static_cast<int*>(p);

Answering the comment code, doing:

int* a = new int; 
void* p = a; 

delete p;

Is never okay. You should never delete through a void*, it's undefined behavior.


side note : in modern C++ you really shouldn't be using new or delete, stick with smart pointers or standard containers.

Hatted Rooster
  • 35,759
  • 6
  • 62
  • 122
  • 1
    What happens if they write `int* a = new int; void* p = a; delete p;`? Is that safe (and possibly what the OP actually needs to know)? – Xirema Jun 13 '18 at 17:15
  • 2
    @Xirema Deleting a void * is undefined. –  Jun 13 '18 at 17:17
  • 1
    see [Deleting via a void pointer is undefined by the C++ Standard](https://stackoverflow.com/a/941959/) – Adrian W Jun 13 '18 at 17:22
2

The short answer is: "It depends".

In most places people say delete only happen when there is new.

That's true so far as it goes. To avoid wasting resources and to ensure all destructors are called correctly every new has to be balanced by a delete somewhere. If your code can follow several paths you have to make sure that every path calls delete (if calling delete is appropriate).

The can get tricky when exceptions are thrown which is one reason why Modern C++ programmers generally avoid using new and delete. Instead they use the smart pointers std::unique_ptr and std::shared_ptr along with the helper template functions std::make_unique<T> and std::make_shared<T> (see the SO question: What is a smart pointer and when should I use one?) to implement a technique known as RAII (Resource Acquisition Is Instantiation).

But in this case, it's not …

Remember that the phrase ... when there is a new refers to the object the pointer points to not the pointer itself. Consider the following code...

int *a = new int();

void *p = a;

if (SomeTest())
{
   delete a;
}
else
{
   a = nullptr;
}

// This line is needed if SomeTest() returned false
// and undefined (dangerous) if SomeTest() returned true
delete static_cast<int *> (p);

Is that last line of code needed?

The object that a and p both point to was created by calling new so delete has to be called on something. If the function SomeTest() returned false then a has been set to nullptr so calling delete on it won't affect the object we created. Which means we do need that last line of code to properly delete the object that was newed up in the first line of code.

On the other hand, if the function SomeTest() returned true then we've already called delete for the object via the pointer a. In that case the last line of code is not needed and in fact may be dangerous.

The C++ standard says that calling delete on an object that has already been deleted results in "undefined behaviour" which means anything could happen. See the SO question: What happens in a double delete?

does C++ itself remember to release that memory?

Not for anything created by calling new. When you call new you are telling the compiler "I've got this, I will release that memory (by calling delete) when appropriate".

do I need to manually delete

Yes: if the object pointed to needs to be deleted here and the void * pointer is the only pointer you can use to delete the object.

Frank Boyne
  • 4,400
  • 23
  • 30