I have a Visual Studio 2008 Windows Mobile 6 C++ application that is using an API that requires the use of LocalAlloc(). To make my life easier, I created an implementation of a standard allocator that uses LocalAlloc() internally:
/// Standard library allocator implementation using LocalAlloc and LocalReAlloc
/// to create a dynamically-sized array.
/// Memory allocated by this allocator is never deallocated. That is up to the
/// user.
template< class T, int max_allocations >
class LocalAllocator
{
public:
typedef T value_type;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
pointer address( reference r ) const { return &r; };
const_pointer address( const_reference r ) const { return &r; };
LocalAllocator() throw() : c_( NULL )
{
};
/// Attempt to allocate a block of storage with enough space for n elements
/// of type T. n>=1 && n<=max_allocations.
/// If memory cannot be allocated, a std::bad_alloc() exception is thrown.
pointer allocate( size_type n, const void* /*hint*/ = 0 )
{
if( NULL == c_ )
{
c_ = LocalAlloc( LPTR, sizeof( T ) * n );
}
else
{
HLOCAL c = LocalReAlloc( c_, sizeof( T ) * n, LHND );
if( NULL == c )
LocalFree( c_ );
c_ = c;
}
if( NULL == c_ )
throw std::bad_alloc();
return reinterpret_cast< T* >( c_ );
};
/// Normally, this would release a block of previously allocated storage.
/// Since that's not what we want, this function does nothing.
void deallocate( pointer /*p*/, size_type /*n*/ )
{
// no deallocation is performed. that is up to the user.
};
/// maximum number of elements that can be allocated
size_type max_size() const throw() { return max_allocations; };
private:
/// current allocation point
HLOCAL c_;
}; // class LocalAllocator
My application is using that allocator implementation in a std::vector<
#define MAX_DIRECTORY_LISTING 512
std::vector< WIN32_FIND_DATA,
LocalAllocator< WIN32_FIND_DATA, MAX_DIRECTORY_LISTING > > file_list;
WIN32_FIND_DATA find_data = { 0 };
HANDLE find_file = ::FindFirstFile( folder.c_str(), &find_data );
if( NULL != find_file )
{
do
{
// access violation here on the 257th item.
file_list.push_back( find_data );
} while ( ::FindNextFile( find_file, &find_data ) );
::FindClose( find_file );
}
// data submitted to the API that requires LocalAlloc()'d array of WIN32_FIND_DATA structures
SubmitData( &file_list.front() );
On the 257th item added to the vector<, the application crashes with an access violation:
Data Abort: Thread=8e1b0400 Proc=8031c1b0 'rapiclnt'
AKY=00008001 PC=03f9e3c8(coredll.dll+0x000543c8) RA=03f9ff04(coredll.dll+0x00055f04) BVA=21ae0020 FSR=00000007
First-chance exception at 0x03f9e3c8 in rapiclnt.exe: 0xC0000005: Access violation reading location 0x01ae0020.
LocalAllocator::allocate is called with an n=512 and LocalReAlloc() succeeds. The actual Access Violation exception occurs within the std::vector< code after the LocalAllocator::allocate call:
0x03f9e3c8
0x03f9ff04
> MyLib.dll!stlp_std::priv::__copy_trivial(const void* __first = 0x01ae0020, const void* __last = 0x01b03020, void* __result = 0x01b10020) Line: 224, Byte Offsets: 0x3c C++
MyLib.dll!stlp_std::vector<_WIN32_FIND_DATAW,LocalAllocator<_WIN32_FIND_DATAW,512> >::_M_insert_overflow(_WIN32_FIND_DATAW* __pos = 0x01b03020, _WIN32_FIND_DATAW& __x = {...}, stlp_std::__true_type& __formal = {...}, unsigned int __fill_len = 1, bool __atend = true) Line: 112, Byte Offsets: 0x5c C++
MyLib.dll!stlp_std::vector<_WIN32_FIND_DATAW,LocalAllocator<_WIN32_FIND_DATAW,512> >::push_back(_WIN32_FIND_DATAW& __x = {...}) Line: 388, Byte Offsets: 0xa0 C++
MyLib.dll!Foo(unsigned long int cbInput = 16, unsigned char* pInput = 0x01a45620, unsigned long int* pcbOutput = 0x1dabfbbc, unsigned char** ppOutput = 0x1dabfbc0, IRAPIStream* __formal = 0x00000000) Line: 66, Byte Offsets: 0x1e4 C++
If anybody can point out what I may be doing wrong, I would appreciate it.
Thanks,
PaulH