Reputation: 59
I spend a lot of time trying to find out why I have an assert in this code.
If there is no destructor in the class, it's work well.
Can you explaine, why I have an Assert whit the class containing destructor.
I dont want to know the number of element in the array. I Just want to understand the Assert when there is a destructor in the class.
With Visual C++, the "new" call the "malloc" function.
=====================================================================================
More detail:
With: CTheClass* pArrayTheClass = new CTheClass[1];
In debug, in the _heap_alloc_dbg_impl() function, you can find the following line of code: blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;
where: sizeof(_CrtMemBlockHeader) : 32 nSize : 4 nNoMansLandSize : 4
After that, the memory is allocated (withHeaderBlock), and the function return the pointer to the data part.
And at the end of "operator new[] " in the "new2.cpp" file, this data pointer is return, to the program allocation.
But With: CTheClassWithDestructor* pArrayTheClassWithDestructor = new CTheClassWithDestructor[1]; is nearly the same thing...
but the nSize is equal to 8; sizeof( int) + 4 bytes
But this time, even if at the end of "operator new[] we have the dataPart pointer.
In the main program I receive this pointer with an offset of 4.
And if I substract 4 from the pointer there is no assert when I call the _msize() function.
That explain the Assert. The assert is cause bt this offset of 4.
Conclusion
This offset of 4 bytes contain the number of element.
If the class have a destructor, the compiler reserve 4 bytes to hold the number of elements in the array.
If there is no destructor to call, we don't have this extra 4 bytes as offset.
Thank's Marc
#include <malloc.h>
class CTheClass
{
private:
int TheValue_;
};
class CTheClassWithDestructor
{
public:
~CTheClassWithDestructor()
{
int TheValue_ = 0;
}
private:
int TheValue_;
};
int _tmain(int argc, _TCHAR* argv[])
{
int size;
CTheClass* pArrayTheClass = new CTheClass[1];
size = _msize(pArrayTheClass);
delete [] pArrayTheClass;
CTheClassWithDestructor* pArrayTheClassWithDestructor
= new CTheClassWithDestructor[1];
size = _msize(pArrayTheClassWithDestructor); /// ASSERT On this line
delete [] pArrayTheClassWithDestructor;
return 0;
}
Upvotes: 0
Views: 336
Reputation: 355387
With Visual C++,
new
calls themalloc
function.
This is partially true: the new
expressions in your code do call operator new
to allocate memory and operator new
does indeed call malloc
. But the pointer to the initial element that is yielded by the new
expression is not necessarily the pointer obtained from malloc
.
If you dynamically allocate an array of objects that require destruction (like your CTheClassWith_string
type), the compiler needs to keep track of how many elements are in the array so that it can destroy them all when you delete
the array.
To keep track of this, the compiler requests a slightly larger block from malloc
then stores some bookkeeping information at the beginning of the block. The new
expression then yields a pointer to the initial element of the array, which is offset from the beginning of the block allocated by malloc
by the bookkeeping information.
Upvotes: 1