I have a Visual Studio 2008 C++ Windows Mobile 6 application where I’m using a FindFirst() / FindNext() style API to get a collection of items. I do not know how many items will be in the list ahead of time. So, I would like to dynamically allocate an array for these items.
Normally, I would use a std::vector<>, but, for other reasons, that’s not an option for this application. So, I’m using LocalAlloc() and LocalReAlloc().
What I’m not clear on is if this memory should be marked fixed or moveable. The application runs fine either way. I’m just wondering what’s ‘correct’.
int count = 0;
INFO_STRUCT* info = ( INFO_STRUCT* )LocalAlloc( LHND, sizeof( INFO_STRUCT ) );
while( S_OK == GetInfo( &info[ count ] )
{
++count;
info = ( INFO_STRUCT* )LocalRealloc( info, sizeof( INFO_STRUCT ) * ( count + 1 ), LHND );
}
if( count > 0 )
{
// use the data in some interesting way...
}
LocalFree( info );
Thanks,
PaulH
Edit: Responders are (not unreasonably) getting hung up on the use of LocalAlloc() over other better options. So I will provide more context.
This chunk of code is being executed from within a RAPI invokable DLL. So, in that context, it looks more like this:
FOO_API int RapiInvokable_Foo( DWORD /*cbInput*/,
BYTE* /*pInput*/,
DWORD* pcbOutput,
BYTE** ppOutput,
IRAPIStream* /*pStream*/ )
{
int count = 0;
INFO_STRUCT* info = ( INFO_STRUCT* )LocalAlloc( LPTR, sizeof( INFO_STRUCT ) );
while( S_OK == GetInfo( &info[ count ] )
{
++count;
info = ( INFO_STRUCT* )LocalRealloc( info, sizeof( INFO_STRUCT ) * ( count + 1 ), LHND );
}
*ppOutput = ( BYTE* )info;
*pcbOutput = sizeof( INFO_STRUCT ) * ( count + 1 );
return S_OK;
}
From the CeRapiInvoke() documentation:
An application should allocate memory for the pInput parameter with the LocalAlloc function. The caller is responsible for freeing pInput. The system allocates memory for the ppOutput parameter. When the application is completed with the buffer, it should free the memory with the LocalFree function.
From what I can tell,
LHNDis not even a valid flag to use in the Windows Mobile version ofLocalAlloc.When you call the non-mobile version of
LocalAllocwithLMEM_MOVEABLE, the return type is notINFO_STRUCT*. The return type isHLOCAL— a handle to the memory that you’ve allocated. It’s not a pointer itself, so it is incorrect to dereference it like a pointer. To get a pointer, you need to useLocalLockto tell the OS that it mustn’t move the memory around for the time being.Consider what MSDN says about movable memory:
So, if you really must use
LocalAlloc, then allocate fixed memory, not movable. That’s the same behavior you’d get from calling plain oldmalloc.The
LMEM_MOVEABLEflag means something different withLocalReAlloc. Whereas withLocalAllocit specifies whether the memory is locked, withLocalReAllocit specifies whether the function is allowed to move the memory in order to satisfy a request for a larger block of memory. If you don’t include that flag withLocalReAlloc, then the function is restricted to changing the block’s size in-place. If there’s no room there, then the function will fail, even if there are larger blocks of memory available elsewhere in the heap.To get the effect of
malloc, callLocalAlloc(LMEM_FIXED). To get the effect ofrealloc, callLocalReAlloc(LMEM_MOVEABLE). IncludeLMEM_ZEROINITin either case if you wish.One thing to take away from all this seems to be that you should only use the flags that the documentation specifically says you can use for each function. For
LocalAlloc, it doesn’t mentionLMEM_MOVEABLE, and forLocalReAlloc, it doesn’t mentionLPTR.