1
typedef ATL::CSimpleMap<WTL::CString,WTL::CString> _Map;
ATL::CSimpleArray<_Map> g_arrMaps;
_Map map;
map.Add(WTL::CString(L"first"),WTL::CString(L"second"));
map.Add(WTL::CString(L"first2"),WTL::CString(L"second2"));
g_arrMaps.Add(map);

//another place _Map has been destructed
for(int i=0;i<g_arrMaps.GetSize();i++){
    _Map m=g_arrMaps[i];
    for(int y=0;y<m.GetSize();y++){
        ATLTRACE(m.GetKeyAt(y)); //error
    }
}

I got error when I want to trace out the data.

Eran
  • 21,632
  • 6
  • 56
  • 89
lovespring
  • 19,051
  • 42
  • 103
  • 153
  • Do you get compiler error? I hope not. Store the returned value in WTL::CString, rather than directly calling ATLTRACE and see if it works. – Ajay Aug 19 '11 at 08:11

2 Answers2

1

CSimpleMap has a good-for-nothing compiler-supplied copy constructor, which merely copies the pointer to its internal buffer. When you add a map to your CSimpleArray, both maps actually share the same data structure. When one goes out of scope and releases memory, it causes the other to become invalid as well. In your case, you might got lucky with accessing already freed CSimpleMap buffer, but that buffer contains CStrings, and once deleted they have released their internal buffers, namely the char arrays.

What you can do:

  1. Avoid using CSimpleMap. It actually does a serial lookup, and it has that horrible default copy constructor. Use CAtlMap instead - its copy constructor is private, so you'll know you're doing something wrong in compile time.
  2. Have the CSimpleArray contain pointers to maps: CSimpleArray<_Map*>. This means extra memory management on your part, but then you avoid the buffer sharing.
  3. Or, you can inherit CSimpleMap or CAtlMap, and provide it a decent copy constructor.
Eran
  • 21,632
  • 6
  • 56
  • 89
0

You can't use types that have non-trivial copy constructors with the simple ATL collections. Those collections use calloc/_recalloc to manage their memory and do not bother copying elements properly.

MSN
  • 53,214
  • 7
  • 75
  • 105