Reputation: 7873
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.
Upvotes: 0
Views: 4603
Reputation: 62333
From the page you link to n your comment to miked's response
"In the linear Windows Embedded CE API environment, there is no difference between the local heap and the global heap. LocalAlloc is equivalent to HeapAlloc(GetProcessHeap, …)."
Clicking the link to go look at CE 6.0 (or Win Mobile 6.0) and you see the same thing.
In fact neww/malloc etc all boild down to a HeapAlloc internally anyway. So I'm really not sure what the issue with just using the C/C++ runtime is ...
Edit:
From this Dr Dobbs link it says:
Using LocalAlloc and LocalReAlloc in this manner exposed a quirk in the Windows CE implementation. In the past, when I used them in a loop like this on NT, I used LPTR as the flag to LocalReAlloc, which allowed me to allocate up to about 512 KB. On Windows CE, this same scenario never allocates more than one KB. This size limitation it too small even for our process list. Changing the LocalReAlloc flag to LMEM_MOVEABLE works on both NT and CE and allows memory up to the size of the biggest free block to be allocated since the location can be moved after the call to LocalAlloc rather than having to be expanded in place.
Upvotes: 2
Reputation: 163357
From what I can tell, LHND
is not even a valid flag to use in the Windows Mobile version of LocalAlloc
.
When you call the non-mobile version of LocalAlloc
with LMEM_MOVEABLE
, the return type is not INFO_STRUCT*
. The return type is HLOCAL
— 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 use LocalLock
to tell the OS that it mustn't move the memory around for the time being.
Consider what MSDN says about movable memory:
The movable-memory flags LHND, LMEM_MOVABLE, and NONZEROLHND add unnecessary overhead and require locking to be used safely. They should be avoided unless documentation specifically states that they should be used.
So, if you really must use LocalAlloc
, then allocate fixed memory, not movable. That's the same behavior you'd get from calling plain old malloc
.
The LMEM_MOVEABLE
flag means something different with LocalReAlloc
. Whereas with LocalAlloc
it specifies whether the memory is locked, with LocalReAlloc
it 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 with LocalReAlloc
, 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
, call LocalAlloc(LMEM_FIXED)
. To get the effect of realloc
, call LocalReAlloc(LMEM_MOVEABLE)
. Include LMEM_ZEROINIT
in 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 mention LMEM_MOVEABLE
, and for LocalReAlloc
, it doesn't mention LPTR
.
Upvotes: 1
Reputation: 3598
According to the MSDN there's no benefit to using the Local functions: http://msdn.microsoft.com/en-us/library/aa366723(VS.85).aspx. Why not just use regular malloc and free or new and delete. They're probably your best bet.
Upvotes: 2