Reputation: 275
I am having a strange issue with a CAtlArray. It works as expected if I use the Add function to add an element to the array. However, if I use SetCount before adding any elements, the program crashes. Strangely, it only works if I add elements directly with the [] operator (I know I know, the documentation says to only use [] to get an element, not to set one). I have been checking that SetCount returns true and it does. Unfortunately, I can't get much debug info easily because this is a dll hooking another process. I can only debug by printing ...
I am wondering if this is typical behavior/if I am missing something (the documentation sucks, google did not return any helpful results, and the ATL code is hard for me to read/follow). My first thought was that SetCount(X) might have some behavior like calling Add() X times and shouldn't be called unless it is expanding the array, but SetAt doesn't work with SetCount either.
Any ideas about what might be going on here?
EDIT:
CAtlArray<MyClass*> arr;
...
size_t initialCount = 10;
if ( arr.SetCount(initialCount) ) {
for ( int i = 0; i < initialCount; i++ ) {
//arr.Add( new MyClass );//Does NOT work
//arr.SetAt( i, new MyClass );//Does NOT work
arr[i] = new MyClass;//This works
}
}
EDIT 2:
I forgot to mention, I also tried using the GetData method but it didn't work either:
MyClass **pData;
if ( arr.SetCount(initialCount) ) {
pData = arr.GetData();
for ( int i = 0; i < initialCount; i++, pData++ ) {
*pData = new MyClass;
}
}
Upvotes: 0
Views: 283
Reputation: 69632
All the three attempts to add elements DO work, but they don't do exactly the same thing, and - more important - the dangerous option does not crash the application and only creates a condition that causes crash later.
//arr.Add( new MyClass );//Does NOT work
//arr.SetAt( i, new MyClass );//Does NOT work
arr[i] = new MyClass;//This works
Let's see what the they actually do:
SetCount
adds 10 NULL
elements to the array
Add
leaves those ten nulls and adds your instances as 11th, 12th and onSetAt
replaces NULL
s with your instancesNULL
s with your instances in the same way as #2 aboveSo items #2 and #3 do "work" and item #1 does a different thing: the array has 20 items and if you later attempt to access the elements, you hit NULL
s where you expect to have valid pointers.
Have a look at small application that prints element count (you can see you have 10 or 20 elements), and then does element checking to verify if all elements of the array are "valid".
#include "stdafx.h"
#include <atlcoll.h>
class MyClass
{
private:
INT m_nValue;
public:
MyClass() :
m_nValue(0xDEADC0DE)
{
}
VOID Check()
{
ATLASSERT(m_nValue == 0xDEADC0DE);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CAtlArray<MyClass*> arr;
size_t initialCount = 10;
if(arr.SetCount(initialCount))
{
for( int i = 0; i < initialCount; i++ )
{
arr.Add( new MyClass );//Does NOT work
//arr.SetAt( i, new MyClass );//Does NOT work
//arr[i] = new MyClass; //This works
}
}
_tprintf(_T("arr.GetCount() %d\n"), arr.GetCount());
for(SIZE_T nIndex = 0; nIndex < arr.GetCount(); nIndex++)
arr[nIndex]->Check();
return 0;
}
An easier way to put elements to the array is as follows:
size_t initialCount = 10;
//if(arr.SetCount(initialCount)) -- not needed
{
for( int i = 0; i < initialCount; i++ )
{
arr.Add( new MyClass );
}
}
Upvotes: 1