Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Heap problem with template class and function

Status
Not open for further replies.

IonelBurtan

Programmer
May 25, 2001
601
RO
I have a template class made in C++ like this

template <class T> class
TypedArray
{
private:
T* m_pArray;
int m_nSize;
int m_nMaxSize;
const int m_nGrowBy;

public:
TypedArray():m_nGrowBy(4), m_nMaxSize(0)
{
m_nSize = 0;
m_nMaxSize = 0;
m_pArray = 0x0;
}
~TypedArray()
{
RemoveAll();
}
int GetSize(){return m_nSize;};
void RemoveAll()
{
delete[] (unsigned char*)m_pArray; // (unsigned char*)= BYTE* from windows
m_pArray = 0x0;
m_nSize = 0;
m_nMaxSize = 0;
}
long GetAt(int i)
{
return m_pArray;
}
void Add(T value)
{
if(m_nSize == m_nMaxSize) //s-a ajuns la dimensiune maxima
{
T* pTemp = new T[m_nMaxSize];
memcpy(pTemp, m_pArray, m_nMaxSize * sizeof(T));
delete[] m_pArray;
m_pArray = new T[m_nMaxSize + m_nGrowBy];
memcpy(m_pArray, pTemp, m_nMaxSize * sizeof(T));
delete[] pTemp;

m_pArray[m_nSize] = value;

m_nSize++;
m_nMaxSize+=m_nGrowBy;
}
else
{
m_nSize++;
m_pArray[m_nSize-1] = value;
}
}
int Find(T value)
{
return GetPositionInVector(m_pArray, &value, m_nSize);
}
};


In Another class CMother i have a member of type
TypedArray<int>** m_pMember alocated dinamically of size

I have problems in ~CMother() like this
{
for(int i=0; i<m_nLocalitatiDelivCount; i++)
for(int j=0; j<m_nLocalitatiDelivCount; j++)
m_arrOraseMinRoad[j].RemoveAll();
DealocaMatrice(m_arrOraseMinRoad, m_nLocalitatiDelivCount); //<--here the code cracks
}

function DealocaMatrice looks like this:

template <typename T>
void DealocaMatrice(T**& aMatrice, unsigned int nCountX)
{
if (aMatrice!=0x0 /*NULL*/)
{
for(unsigned int i=0; i<nCountX; i++)
delete aMatrice;
delete[] aMatrice; //<-here the codestops

aMatrice = 0x0;// NULL fara windows.h
}
}

TypedArray has no memory leaks and RemoveAll just leaves the heap OK. Also, function DealocaMatrice works fine in many other instances, the code is ok.
The error I get is a an ASSERT:
_BLOCK_TYPE_IS_VALID() coming from dbgdel.cpp

It just looks like I have a problem when I dealloc a heap matrix made of heap arrays. Pretty unusual situasion but I do not see why it does not works.

Tnx,
Any clue really apreciated,

s-)

Blessed is he who in the name of justice and goodwill, sheperds the weak through the valley of darkness...
 
how about (unsigned char*) in destructor when your T type is int and the array is int*?

Ion Filipski
1c.bmp
 
Show the code for allocating m_arrOraseMinRoad. Also, repost the code you posted but put it into
Code:
tags. The subscripts were getting seen as italics tags by the TGML. Use the Preview Post button to make sure it looks right.

And is type T a CTypedArray<int> for the offending call to DeallocaMatrice?
 
yes indeed the type is int. the function that allocates the matrix is:

Code:
template <typename T> 
void AlocaMatrice(T**& aMatrice, unsigned int nCountX, unsigned int nCountY)
{
	if (nCountX == 0 || nCountY == 0){aMatrice = 0x0; return;};

	aMatrice = new T*[nCountX];
	for(unsigned int i=0; i<nCountX; i++)
		aMatrice[i] = new T[nCountY];
}

IonFilipski, do u suggest that I cast the pointer to (unsigned char*) or BYTE (i have seen that in MFC classes) before deallocating. Will this work for any type of T. Because, I would not like to test the type of T inside DealocaMatrice.

If so,why is it a problem with &quot;int&quot; deallocations.

tnx,
I think I may be on the right track...

s-)

Blessed is he who in the name of justice and goodwill, sheperds the weak through the valley of darkness...
 
Bellow is all the code you need to reproduct the situation in a console program.. Just put it in console project, compile it, run it in debug and you will get the assert

// TestLongArray.cpp : Defines the entry point for the console application.
//

#include &quot;stdafx.h&quot;
#include <stdio.h>
#include <string.h>
#include <crtdbg.h>

template <typename T>
void AlocaMatrice(T**& aMatrice, unsigned int nCountX, unsigned int nCountY)
{
if (nCountX == 0 || nCountY == 0){aMatrice = 0x0; return;};

aMatrice = new T*[nCountX];
for(unsigned int i=0; i<nCountX; i++)
aMatrice = new T[nCountY];
}

template <typename T>
void DealocaMatrice(T**& aMatrice, unsigned int nCountX)
{
if (aMatrice!=0x0 /*NULL*/)
{
for(unsigned int i=0; i<nCountX; i++)
delete aMatrice; //<--here the code stops
delete[] aMatrice;

aMatrice = 0x0;// NULL fara windows.h
}
}

template <class T> class
TypedArray
{
private:
T* m_pArray;
int m_nSize;
int m_nMaxSize;
const int m_nGrowBy;

public:
TypedArray():m_nGrowBy(4), m_nMaxSize(0)
{
m_nSize = 0;
m_nMaxSize = 0;
m_pArray = 0x0;
}
~TypedArray()
{
RemoveAll();
}
int GetSize(){return m_nSize;};
void RemoveAll()
{
delete[] (unsigned char*)m_pArray;
m_pArray = 0x0;
m_nSize = 0;
m_nMaxSize = 0;
}
long GetAt(int i)
{
return m_pArray;
}
void Add(T value)
{
if(m_nSize == m_nMaxSize) //s-a ajuns la dimensiune maxima
{
T* pTemp = new T[m_nMaxSize];
memcpy(pTemp, m_pArray, m_nMaxSize * sizeof(T));
delete[] (unsigned char*)m_pArray;
m_pArray = new T[m_nMaxSize + m_nGrowBy];
memcpy(m_pArray, pTemp, m_nMaxSize * sizeof(T));
delete[] (unsigned char*)pTemp;

m_pArray[m_nSize] = value;

m_nSize++;
m_nMaxSize+=m_nGrowBy;
}
else
{
m_nSize++;
m_pArray[m_nSize-1] = value;
}
}
int Find(T value)
{
return GetPositionInVector(m_pArray, &value, m_nSize);
}
};

void Test()
{
TypedArray<int>** m_arr;
AlocaMatrice(m_arr, 2, 2);

m_arr[0][0].Add(10);
m_arr[0][0].Add(11);
m_arr[0][1].Add(10);
m_arr[0][1].Add(11);
m_arr[1][0].Add(10);
m_arr[1][0].Add(11);
m_arr[1][1].Add(10);
m_arr[1][1].Add(11);

for(int i=0; i<2; i++)
for(int j=0; j<2; j++)
m_arr[j].RemoveAll();

_CrtDumpMemoryLeaks( );
DealocaMatrice(m_arr, 2);

TypedArray<int> l;
l.Add(1);
l.Add(2);
l.Add(3);
l.Add(4);
l.Add(5);
printf(&quot;%d\n&quot;, l.GetAt(2));
l.Add(6);
l.Add(7);
l.Add(8);
l.RemoveAll();

TypedArray<long> g;
g.Add(9);
g.Add(10);
g.Add(11);
g.Add(12);
g.Add(13);

printf(&quot;%d, %d\n&quot;, g.GetAt(2), g.GetAt(1));
}

int main(int argc, char* argv[])
{
int tmpDbgFlag;
tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
tmpDbgFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF;
tmpDbgFlag |= _CRTDBG_ALLOC_MEM_DF;
_CrtSetDbgFlag(tmpDbgFlag);

Test();

_CrtDumpMemoryLeaks( );

return 0;
}

Tnx,

s-)

Blessed is he who in the name of justice and goodwill, sheperds the weak through the valley of darkness...
 
Why do you cast a T* to a char* before deletion? Wont that interfere with the new/delete mechanism as delete is expecting a T* isn't it??
 
Yes, you have seen it right. But it does not afect dthe deletition problem. The cast is made for some memory representation of 4 bit types (like int, long etc). If you look in MFC at sources for CDwordArray you will see the same thing.

the problem was in line:
delete aMatrice; //<--here the code stops

which should have been:
delete[] aMatrice;


s-)

Blessed is he who in the name of justice and goodwill, sheperds the weak through the valley of darkness...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top