简体   繁体   中英

CAtlArray strange behavior using SetCount

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;
  }
}

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
    1. following Add leaves those ten nulls and adds your instances as 11th, 12th and on
    2. following SetAt replaces NULL s with your instances
    3. following indexed set replaces NULL s with your instances in the same way as #2 above

So 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 );
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM