How to free a void pointer.
struct vStruct {
void *vPtr;
struct vStruct *next;
};
struct vStruct sObj;
struct vStruct *sObjNew = sObj;
delete sObjNew->vPtr; -----------> Is this correct way to delete void pointer
delete sObjNew;
Showing error Operator 'delete', applied to void* argument having has undefined behavior, and most likely does not invoke the object's destructor.
You do not delete a void pointer. Why? Because:
'delete', applied to void* argument has undefined behavior, and most likely does not invoke the object's destructor.
How would your compiler know which type the pointee object has? And therefore which destructor to call? (Though it can probably determine how much memory to free, depending on the allocation mechanism.)
Do not store a void* — use a "real" pointer type instead. If you need to "hide" the true type, consider employing polymorphism instead of antiquated C practices.
You should not delete a void pointer. delete works for specific types (such that compiler knows, which destructor should be called - as stated in error message).
If you want to hold unspecified type in your structure, you have to wrap it somehow.
class DataWrapper
{
public:
virtual void * GetData() = 0;
virtual ~DataWrapper()
{
}
};
class MyDataWrapper
{
protected:
MyData * data;
public:
MyDataWrapper(MyData * newData)
{
data = newData;
}
void * GetData()
{
return data;
}
~MyDataWrapper()
{
delete data;
}
};
struct vStruct
{
MyDataWrapper * vPtr;
struct vStruct *next;
~vStruct()
{
if (vPtr != null)
delete vPtr;
}
};
vStruct sObj;
sObj.vPtr = new MyDataWrapper(new MyData());
// When sObj gets deleted, MyDataWrapper is
// deleted too (thanks to the ~vStruct) and
// in effect, the allocated data is deleted too.
Note, that it's a simple example, it can be written more aesthetically.
How was vPtr initialised?
If it points to data the struct doesn't own, you must not destroy it.
If it points to data created using malloc, you should call free.
If it points to data created using new, you'd need to cast it to the correct (or a compatible) type before calling delete to allow the correct destructor to be called.
Note that your example code won't compile but suggests vPtr is not being initialised at all. You must initialise vPtr in all vStruct instances you create. Attempting to free an uninitialised vPtr would have undefined consequences but would likely crash.
Related
I am using polymorphism with virtual functions and need to define a pointer as a child object type before using it. For example:
struct object {
virtual void function() {}
};
struct object_child : object {
int a;
int b;
void function() {std::cout<<"working";}
};
int main() {
uint64_t sandbox[512];
object * o1 = new ((void *) &sandbox[0]) object_child();
o1->function();
}
This works fine except that the memory at the location is overwritten. Is there a cast or some operator I can use that would result in the same o1 without overwriting the memory location?
*** EDIT - SK - Adding cout to function -
You say the bytes at 0x20000 match the data structure layout of object_child, but it actually doesn't. Namely, you're overlooking that an object_child has an invisible member you're not accounting for - the virtual function pointer. Which means no pointer cast will work, period. You'll have to create an actual object_child object with it's own copy of that state.
For example
//somewhere
struct IFace;
struct Base
{
Base(IFace* iface):
f(iface)
{
//will not use iface here
}
private:
IFace* f;
};
struct Data;
struct Implementation
{
private:
friend IFace* factory_create(Data*);
Implementation(Data* data): // ok, it's not private, just some internal
// class not mentioned in public headers
d(data)
{
//will not deref data here
}
private:
Data* d;
};
IFace* factory_create(Data* data)
{
return new Implementation(data);
}
//here
struct Derived: Base
{
Derived():
Base(factory_create(&data)) //using pointer to uninitialized member
{
//will fill data here
}
Data data;
};
Seems I have no chance to create data before passing pointer to it to factory_create function.
Is this code safe? If not, what minimal changes should I do to make it safe?
The pointer is safe and valid, and can be used as long as you don't dereference it. It's a fairly common practice to store the ponter value in registry to be used later when it is fully constructed.
Similar story with passing 'this' that also is subject to warning, that even can be used limiting to the already constructed elements.
[class.cdtor]/3
To form a pointer to (or access the value of) a
direct non-static member of an object obj, the construction of obj
shall have started and its destruction shall not have completed,
otherwise the computation of the pointer value (or accessing the
member value) results in undefined behavior.
I've been meddling around, testing for memory leaks with Intel Inspector, when I noticed something that should not be. I inherit from std::vector which is not supposed to have a virtual destructor, I have an extra member in the derived class, I do dynamic memory allocation on it, in main I create a derived class on the heap, cast to base class, call delete... and no memory leak is detected??? By all logic, I should get a memory leak.
template <typename T>
class DynamicArray : public std::vector<T> {
public:
DynamicArray() : children(nullptr) {
children = new int(50);
}
~DynamicArray() {
if (children) delete children;
}
DynamicArray& operator<<(const T& value)
{
push_back(value);
return *this;
}
private:
int *children;
};
int main() {
DynamicArray<int> *pArray = new DynamicArray<int>;
(*pArray) << 4 << 5;
static_cast<std::vector<int>*>(pArray);
delete pArray;
}
pArray is still of type DynamicArray<int> and wiil call the right destructor, this would likely leak:
std::vector<int>* wrong = static_cast<std::vector<int>*>(pArray);
delete wrong;
edit: as Ben Voigt correctly mentioned, this last code snippet actually undefined behavior since the destructor of std::vector is not virtual. So it is not even guaranteed that this will leak
This expression has no side-effects:
static_cast<std::vector<int>*>(pArray);
In your code, the delete and new actually match perfectly.
Also, this line allocates ONE int, so you may not notice it in your memory analysis:
children = new int(50);
I am implementing standart template tree structure, and I came across small problem.
Idea that each node will hold pointer to some data. Later in order to delete element correctly I need to know if its a single pointer or pointer to an array.
Inside of my tree->ReleaseMemory() method I have this code:
if (node->_data != NULL) {
switch (_destructionMethod){
case tree_delete:
delete node->_data; break;
case tree_deleteList:
delete [] node->_data; break;
case tree_free:
free(node->_data); break;
}
}
where _destructionMethod has been set during initialisation of the node.
Is there any way I can choose correct destructor without predefining it in special variable for it during initialisation ?
Thanks!
First basic:
delete is used when you allocate memory with new:
int *p = new int;
int *a = new int[10];
//...
delete p;
delete []a; //note the difference!
free is used when you allocate memory with malloc:
int *p = (int*)malloc(sizeof(int) * 1);
int *a = (int*)malloc(sizeof(int) * 10);
//...
free(p);
free(a); //no difference!
Now your problem:
Is there any way I can choose correct destructor without predefining it in special variable for it during initialisation
Consider policy-based design. That means, write allocator that will encapsulate allocation and deallocation in a class and use that consistently in your code.
No, there is no portable way to find out what allocator a particular pointer originally came from.
There's no way to interrogate a pointer to find out how it was allocated, but a common idiom is to give the allocated object itself responsibility for its own destruction. It looks like your object types are not all class types, though, so you would need to wrap them in order to do this. For example:
class destroyable_node
{
virtual void destroy() = 0;
};
template <typename T> class object_node : public destroyable_node
{
private:
T * value_;
public:
// Presumes T is copy-constructable.
object_node(T value) : value_( new T(value) ) {}
operator T&() {return value_;}
operator T const &() const {return value_;}
void destroy() {delete value_;}
};
template<typename T> class array_node : public destroyable_node
{
private:
T * value_;
public:
array_node(T[] value)
: value_( new T[ sizeof(value)/sizeof(T) ] )
{
std::copy(value, value + sizeof(value)/sizeof(T), value_);
}
operator T*() {return value_;}
operator T const *() const {return value_;}
void destroy() {delete[] value_;}
};
...and so on.
Don't do this at all. Use a smart pointer, like shared_ptr from C++0x or Boost or if that is not an option, auto_ptr from C++. If you could have more than one object, consider using std::vector.
Manual resource management is messy and difficult to get right.
Maybe a better design is to implement an abstract interface used by your container with three concrete subclasses that know what kind of thing they hold pointers to. Your container would simply call a destroy() method in the base class and let the derived classes worry about calling the correct destructor.
I have the following class:
class Stack {
struct Link {
void* data;
Link* next;
void initialize(void* dat, Link* nxt);
}* head;
public:
void initialize();
void push(void* dat);
void* peek();
void* pop();
void cleanup();
};
The pop method is:
void* Stack::pop() {
if(head == 0) return 0;
void* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}
oldHead is a pointer to a struct Link, which has a void pointer as member. So by deleting oldHead I'm implicitly deleting that void pointer, right?
I'm reading Thinking in C++ by Bruce Eckel, and it says that deleting void pointers doesn't clean things up properly because delete needs to know the type of the pointer.
This code is implicitly deleting the void pointer data, so: Can someone explain why is this (implicit) way of deleting a void pointer different from deleting with delete <void pointer>?
Your terminology is causing ambiguity, but let me explain. Let's say you have:
struct foo
{
void* bar;
};
Whenever a foo ends its lifetime, bar simply stops existing too. So if you have:
{
foo f = { new int; }
}
You've leaked, as new int is never deleted. Likewise, when you do:
{
foo* f = new foo;
f->bar = new int;
delete f;
}
You've still leaked, since when delete f is run, you simply end the lifetime of what f is pointing to (just like what happened automatically above), ergo bar simply ceases to exist and the new int is not deleted.
To summarize, when an object's lifetimes ends, delete is not called on the members that are a pointer.
So when you call delete on a Link, it's the same situation as bar in foo above: you're deleteing the memory for a Link causing data to stop existing, but not actually deleting what it's pointing at.
By deleting Link, that void* memory space is not being deleted. You need to define a destructor which deletes the memory that has been allocated. Each new needs one delete. An example of this for the Link-struct would be to add a destructor that deletes data. If your assumption would be correct, then next would also be deleted, causing your entire linked-list to be deleted which would be a terrible behavior.
Calling delete on a pointer will call the destructor of the pointed to type. If that type has no destructor, no such destructor will be called. This is the case for a void pointer which doesn't have a destructor. In the case of inheritance, the destructor should always be virtual so that the deepest class in the hierarchy will have their destructor called. The memory will be correctly free'd even if you cast your pointers to the wrong types - it's just that the destructor will be called incorrectly.
"I'm implicitly deleting that void pointer, right?"
Well, you're deleting the pointer itself when you delete oldHead. You're not deleting or freeing its target, which is what you seem to be wanting, and is what happens when you call delete on a pointer.
(To see why this is the case, consider that you might define a struct with a void* pointer that points to something outside the struct. You wouldn't want the target to be freed just because the struct was deleted.)
One problem with deleting a void pointer happens when you are pointing to something with a destructor:
#include <iostream>
struct foo
{
~foo() { std::cout << "important work" << std::endl; }
};
int main()
{
foo *f = new foo;
void *v = f;
delete v;
}
If you run the code sample above, you will see that the destructor is never called.