UnBinBonGars
UnBinBonGars

Reputation: 59

_msize Debug Assertion Failed

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.

But why we have 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

Answers (1)

James McNellis
James McNellis

Reputation: 355387

With Visual C++, new calls the malloc 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

Related Questions