Использование LocalAlloc и LocalRealloc - PullRequest
0 голосов
/ 07 мая 2010

У меня есть приложение Visual Studio 2008 C ++ для Windows Mobile 6, в котором я использую API в стиле FindFirst () / FindNext () для получения коллекции элементов. Я не знаю, сколько предметов будет в списке раньше времени. Итак, я хотел бы динамически выделить массив для этих элементов.

Обычно я бы использовал std::vector<>, но по другим причинам это не вариант для этого приложения. Итак, я использую LocalAlloc() и LocalReAlloc().

Что мне неясно, так это то, должна ли эта память быть помечена как фиксированная или подвижная. Приложение работает в любом случае. Мне просто интересно, что «правильно».

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

Спасибо, PaulH


Редактировать: Ответчики (не без оснований) зацикливаются на использовании LocalAlloc () по сравнению с другими лучшими параметрами. Поэтому я предоставлю больше контекста.

Этот фрагмент кода выполняется из вызываемой библиотеки RAPI. Итак, в этом контексте это выглядит примерно так:

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

Из документации CeRapiInvoke () :

Приложение должно выделить память для параметра pInput с помощью функции LocalAlloc. Звонящий отвечает за освобождение pInput. Система выделяет память для параметра ppOutput. Когда приложение заполнено буфером, оно должно освободить память с помощью функции LocalFree.

Ответы [ 3 ]

2 голосов
/ 07 мая 2010

Со страницы, на которую вы ссылаетесь, ваш комментарий к ответу miked

"В линейной среде Windows Embedded CE API нет разницы между локальной кучей и глобальной кучей. LocalAlloc эквивалентно HeapAlloc (GetProcessHeap,…). "

Щелкнув ссылку, чтобы перейти к CE 6.0 (или Win Mobile 6.0), и вы увидите то же самое.

Фактически neww / malloc и т. Д. Все сводятся кHeapAlloc внутренне в любом случае.Так что я действительно не уверен, в чем проблема с использованием среды выполнения C / C ++ ...

Edit:

Из этой ссылки Dr Dobbs написано:

Использование LocalAlloc и LocalReAlloc таким способом выявило причину в реализации Windows CE.В прошлом, когда я использовал их в цикле, подобном этому, в NT, я использовал LPTR в качестве флага для LocalReAlloc, что позволяло мне выделять до 512 КБ.В Windows CE этот сценарий никогда не выделяет более одного КБ.Это ограничение по размеру слишком мало даже для нашего списка процессов.Изменение флага LocalReAlloc на LMEM_MOVEABLE работает как для NT, так и для CE и позволяет выделять память до размера самого большого свободного блока, поскольку местоположение можно перемещать после вызова LocalAlloc, а не расширять его на месте.

2 голосов
/ 07 мая 2010

Согласно MSDN, использование функций Local бесполезно: http://msdn.microsoft.com/en-us/library/aa366723(VS.85).aspx. Почему бы просто не использовать обычные malloc и free или new и delete. Они, вероятно, ваша лучшая ставка.

1 голос
/ 07 мая 2010

Из того, что я могу сказать, LHND даже не является допустимым флагом для использования в версии Windows Mobile LocalAlloc.

Когда вы вызываете немобильную версию LocalAlloc с LMEM_MOVEABLE, тип возврата - , а не INFO_STRUCT*. Тип возвращаемого значения - HLOCAL - дескриптор для выделенной памяти. Это не сам указатель, поэтому неправильно разыменовывать его как указатель. Чтобы получить указатель, вам нужно использовать LocalLock, чтобы сообщить ОС, что в данный момент она не должна перемещать память.

Рассмотрим , что MSDN говорит о подвижной памяти :

Флаги подвижной памяти LHND, LMEM_MOVABLE и NONZEROLHND добавляют ненужные издержки и требуют безопасного использования блокировки. Их следует избегать, если в документации конкретно не указано, что их следует использовать.

Итак, если вам действительно нужно использовать LocalAlloc, тогда выделите фиксированную память, а не подвижную. Это то же самое поведение, которое вы бы получили, если бы позвонили старому malloc.

Флаг LMEM_MOVEABLE означает что-то другое с LocalReAlloc. Принимая во внимание, что LocalAlloc указывает, заблокирована ли память, а LocalReAlloc указывает, разрешено ли функции перемещать память, чтобы удовлетворить запрос на больший блок памяти. Если вы не включите этот флаг с LocalReAlloc, то функция будет ограничена изменением размера блока на месте. Если там нет места, то функция завершится ошибкой, даже если где-то в куче будет больше блоков памяти.

Чтобы получить эффект malloc, позвоните LocalAlloc(LMEM_FIXED). Чтобы получить эффект realloc, звоните LocalReAlloc(LMEM_MOVEABLE). Включите LMEM_ZEROINIT в любом случае, если хотите.

Одна вещь, которую нужно отнять от всего этого, это то, что вы должны использовать только те флаги, которые в документации конкретно указано, что вы можете использовать для каждой функции. Для LocalAlloc не упоминается LMEM_MOVEABLE, а для LocalReAlloc не упоминается LPTR.

...