Dynamically allocated structure and casting
Let's say I have a first structure like this:
typedef struct {
int ivalue;
char cvalue;
}
Foo;
And a second one:
typedef struct {
int ivalue;
char cvalue;开发者_JAVA技巧
unsigned char some_data_block[0xFF];
}
Bar;
Now let's say I do the following:
Foo *pfoo;
Bar *pbar;
pbar = new Bar;
pfoo = (Foo *)pbar;
delete pfoo;
Now, when I call the delete operator, how much memory does it free?
sizeof(int) + sizeof(char)
Or
sizeof(int) + sizeof(char) + sizeof(char) * 0xFF
?
And if it's the first case due to the casting, is there any way to prevent this memory leak from happening?
Note: please don't answer "use C++ polymorphism" or similar, I am using this method for a reason.
The amount of memory freed is undefined - your code is illegal in C++.
It will probably (there is no guarantee) work fine on your machine as with most implementations of delete
(when freeing the memory) it doesn't matter what type the pointer is but the address. Due to that it will probably deallocate the memory allocated for Bar (in this case).
However, view delete as expanding to something like:
if ( ptr != 0 ){
ptr->~ClassName();
operator delete(ptr);
}
Consider the case where you pass the wrong type to delete
. The wrong destructor gets called which won't result at an error at compile time but might cause an issue at run time.
Consider the case where the new and delete operators are overloaded...
The whole idea of such code is just undefined behavior. Don't do it. What happens if someone overloads operator new
and operator delete
for one struct and not for the other?
The only legal way to do what you want is to inherit both structs from the comon base with a virtual destructors - then you will have proper defined behavior and no problems with deallocation.
However if operator new
and operator delete
are not overloaded and both structs have trivial destructors it might just work allright on your implementation - the compiler will call ::operator delete()
that has one parameter - the address of the block and it will free exactly the right amount of memory. However don't count on it - your code actually has undefined behavior.
Don't worry, the amount of memory to be deleted is written inside of allocated memory block header, so your code will not leak anything and delete exactly what have been allocated. But the above will not be true if you will allocate it as array.
Aside from matters of language law, your code will, in practice, do the right thing and deallocate the entire object. Most compilers will just invoke the underlying malloc/free (or similar) when new/delete is invoked.
It will matter, however, if you have a non-trivial destructor in Bar
. The lack of a virtual destructor means that only the base class destructor gets called when you delete through a base-class pointer.
IIRC, failure to call the derived destructor is the only caveat with the above code. Other than that, I believe it is valid code. (My C++ is rusty these days, so I could be way off the mark.)
Agree with alemjerus - this doesn't create memory leak. My two cents: sizeof(int) + sizeof(char) may not be equal to sizeof(Foo) because of structure elements padding, so allocated/deallocated memory block size is sizeof(Foo).
精彩评论