Yes, I'm using a Dynamic Array, not STL. I thought that in this case the memory allocation and de-allocation is simple. It should be, but something is wrong and I don't know what.
Here is the offending function:
void GPPopulation::CrossOver(GPTreeData &CrossOver1, GPTreeData &CrossOver2)
{
GPNode* Tree[2]={CrossOver1.Tree,CrossOver2.Tree};
if(Tree[0]==NULL || Tree[1]==NULL)
{
Mutate(CrossOver1);
Mutate(CrossOver2);
return;
}
unsigned Choice[2];
{
unsigned NumNodes[2];
unsigned DataTypes[2];
DataType* DataTypeArray[2];
for(unsigned J=0; J<2; J++)
{
unsigned Temp=0;
NumNodes[J]=Tree[J]->Count();
DataTypeArray[J]=new DataType[NumNodes[J]];
DataTypes[J]=Tree[J]->NodeDataTypes(DataTypeArray[J],Temp);
}
unsigned AllDataTypes=DataTypes[0]&DataTypes[1];
Choice[0]=GetChoice(DataTypeArray[0], NumNodes[0], AllDataTypes);
Choice[1]=GetChoice(DataTypeArray[1], NumNodes[1], DataTypeArray[0][Choice[0]]);
for(unsigned K=0; K<2; K++)
delete [] DataTypeArray[K];//<-------Here is the offending statement
}
GPNode* Nodes[2];
GPNode* Parents[2];
for(unsigned J=0; J<2; J++)
{
Nodes[J]=Tree[J]->Find(Choice[J]);
Parents[J]=Nodes[J]->GetParent();
}
for(unsigned K=0; K<2; K++)
Parents[K]->SwitchChild(Nodes[K],Nodes[(K+1)%2]);
}
As you can see, I clearly have used the delete operator for every new operator, and I clearly have used the new operator for every delete operator. But the debugger acts like I am trying to delete data that has already been deleted.
And, yes, this I am trying out Genetic Programming, but my problem isn't AI related.
Here are the functions that use DataTypeArray in them:
unsigned GPNode::NodeDataTypes(DataType* &DataTypeArray, unsigned &Index)
{
unsigned Types=DataTypeArray[Index]=ReturnType;
Index++;
for(unsigned K=0; K<NumChildren; K++)
Types|=Children[K]->NodeDataTypes(DataTypeArray,Index);
return Types;
}
unsigned GPPopulation::GetChoice(DataType* DataTypeArray, unsigned ArrayLength, unsigned AcceptableDataTypes)
{
unsigned NumAcceptable=0;
for(unsigned J=0; J<ArrayLength; J++)
if(DataTypeArray[J]&AcceptableDataTypes)
NumAcceptable++;
unsigned Choice=rand()%NumAcceptable;
bool Found=false;
unsigned Index=0;
for(unsigned K=0; !Found; K++)
{
if(DataTypeArray[K]&AcceptableDataTypes)
{
if(Choice==Index)
{
Choice=K;
Found=true;
}
Index++;
}
}
return Choice;
}
Now, the weird thing is that I never get an error the first time around. But if any of the inputs into the cross-over function have been inputs into the function before, there will be an error (I think that's what's causing it anyway, but I'm not entirely sure).
O.K. Here is some data on the error I get:
Here is the Call Stack up to CrossOver()
ntdll.dll!77f75554()
ntdll.dll!77f9c106()
ntdll.dll!77f82566()
ntdll.dll!77f9c4fd()
ntdll.dll!77f8beac()
kernel32.dll!77e733fb()
kernel32.dll!77e6c936()
Genetic Programming.exe!_CrtIsValidHeapPointer(const void * pUserData=0x016320c0) Line 1807 C
Genetic Programming.exe!_free_dbg(void * pUserData=0x016320c0, int nBlockUse=1) Line 1132 + 0x9 C
Genetic Programming.exe!operator delete(void * pUserData=0x016320c0) Line 54 + 0x10 C++
Genetic Programming.exe!operator delete[](void * p=0x016320c0) Line 21 + 0x9 C++
Genetic Programming.exe!GPPopulation::CrossOver(GPPopulation::GPTreeData & CrossOver1={...}, GPPopulation::GPTreeData & CrossOver2={...}) Line 185 + 0x23 C++
The error brings the debugger to dbgheap.c:
_CRTIMP int __cdecl _CrtIsValidHeapPointer(
const void * pUserData
)
{
#ifndef WINHEAP
int i;
void * base;
#endif /* WINHEAP */
if (!pUserData)
return FALSE;
if (!_CrtIsValidPointer(pHdr(pUserData), sizeof(_CrtMemBlockHeader), FALSE))
return FALSE;
#ifdef WINHEAP
#ifndef _WIN64
if ( __active_heap == __V6_HEAP )
{
PHEADER pHeader;
if (pHeader = __sbh_find_block(pHdr(pUserData)))
{
return __sbh_verify_block(pHeader, pHdr(pUserData));
}
else if ( (_osver & 0x8000) != 0 )
return TRUE;
else
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}
#ifdef CRTDLL
else if ( __active_heap == __V5_HEAP )
{
__old_sbh_region_t * preg;
__old_sbh_page_t * ppage;
__old_page_map_t * pmap;
if ( (pmap = __old_sbh_find_block( pHdr(pUserData), &preg, &ppage )) !=
NULL )
{
if ( *pmap )
return TRUE;
else
return FALSE;
}
else if ( (_osver & 0x8000) != 0 )
return TRUE;
else
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}
#endif /* CRTDLL */
else // __active_heap == _SYSTEM_HEAP
#endif /* _WIN64 */
{
return HeapValidate( _crtheap, 0, pHdr(pUserData) );
}
#else /* WINHEAP */
/*
* Go through the heap regions and see if the pointer lies within one
* of the regions of the local heap.
*
* Pointers from non-local heaps cannot be handled. For example, a
* non-local pointer may come from a DLL that has the CRT linked-in.
*
*/
for (i = 0; (base = _heap_regions._regbase) != NULL &&
i < _HEAP_REGIONMAX; i++)
{
if (pUserData >= base && pUserData <
(void *)(((char *)base)+_heap_regions._currsize))
return TRUE;
}
return FALSE;
#endif /* WINHEAP */
}
It points to the closing bracket at the end.
Here is the Debug Output:
HEAP[Genetic Programming.exe]: Heap block at 01632098 modified at 01635488 past requested size of 33e8
Unhandled exception at 0x77f75554 in Genetic Programming.exe: User breakpoint.
That should be enough information, don't you think?
I am the master of ideas.....If only I could write them down...