C# освобождают память, на которую ссылается IntPtr

Я использую некоторый неуправляемый код, который возвращает указатели (IntPtr) большим объектам изображения. Я использую ссылки, но после того, как я закончен с изображениями, я должен освободить ту память, на которую ссылаются указатели. В настоящее время единственная вещь, которая освобождает память, состоит в том, чтобы завершить работу моего целого приложения. Я должен смочь освободить ту память из своего приложения.

Вот вызов к этому, выделяет память. hbitmap указатель, который возвращается и должен быть освобожден.

[DllImport("twain_32.dll", EntryPoint = "#1")]
public static extern TwainResult DsImageTransfer(
    [In, Out] Identity origin, [In] Identity dest, DataGroup dg, 
    DataArgumentType dat, Message msg, ref IntPtr hbitmap);
10
задан casperOne 20 February 2010 в 00:06
поделиться

6 ответов

Это зависит от того, как была выделена эта память. Класс Marshal имеет методы для деаллокации памяти, выделенной через общие шаблоны распределения interop, например FreeCoTaskMem. Если неуправляемый код использует способ выделения, не совместимый с Interop, то вы не сможете взаимодействовать с ним.

Обновлено

Если я рискну предположить, то функция #1, которую вы вызываете в twain_32.dll - это функция DS_ENTRY в TWAIN-провайдере. Спецификации Twain называют протокол управления ресурсами памяти:

Memory Management in TWAIN 2.0 and выше
TWAIN требует, чтобы приложения и Источники должны управлять памятью друг друга. Основной проблемой является гарантия соглашение об использовании API. TWAIN 2.0 вводит четыре новые функции, получаемые от менеджера источников через DAT_ENTRYPOINT.

TW_HANDLE PASCAL DSM_MemAllocate (TW_UINT32)
PASCAL DSM_MemFree (TW_HANDLE)
TW_MEMREF PASCAL DSM_MemLock(TW_HANDLE)
void PASCAL DSM_MemUnlock(TW_HANDLE)

Эти функции соответствуют функциям глобальной памяти WIN32. функции глобальной памяти WIN32 упомянутым в предыдущих версиях спецификации TWAIN: GlobalAlloc, GlobalFree, GlobalLock, GlobalUnlock
На MacOS/X эти функции вызывают следующие функции NewPtrClear and DisposePtr. Блокировка и разблокировка - это функции без операций, но они все равно должны быть вызваны. TWAIN 2.0 совместимые приложения и источники должны использовать эти вызовы на всех платформах (Windows, MacOS/X и Linux). Менеджер источников берет на себя ответственность за то, чтобы убедиться, что все компоненты используют одинаковые API управления памятью.

Поэтому для освобождения ресурсов вы должны вызвать DSM_MemFree, что предположительно на Win32 платформах будет реализовано через GlobalFree, или Marshal.FreeHGlobal.

Поскольку это в основном мои домыслы, вам лучше проверить спецификацию конкретной реализации TWAIN, которую вы используете.

4
ответ дан 3 December 2019 в 21:59
поделиться

Вам нужно использовать конкретный механизм выделения памяти, который был использован для выделения памяти в первую очередь.

Так, если вы использовали COM и IMalloc интерфейс для выделения памяти, то вы должны передать IntPtr обратно в Free метод этой реализации, чтобы освободить выделенную память.

Если вы действительно используете COM-распределитель, возвращаемый вызовом CoGetMalloc, то вы можете вызвать статический FreeCoTaskMem метод на Marshal классе.

Класс Marshal также имеет метод для освобождения памяти, выделенной через вызов LocalAlloc под названием FreeHGlobal.

Однако, и это распространенный случай, если память была выделена оператором new в C++ или вызовом malloc в C, то вы должны выставить функцию в неуправляемом коде через interop, которая освободит память соответствующим образом.

В случае C++, вы должны выставить функцию, которая принимает указатель и просто вызывает delete для этого указателя. В случае malloc, вы создадите функцию, которая принимает указатель и вызывает free для этого указателя.

Что касается конкретно вашего вопроса, похоже, что DsImageTransfer - это API, специфичный для конкретного производителя (боюсь, что не слишком доступный в Интернете), поэтому требуется больше информации о конкретной функции API и о том, как она выделяет память. Простое знание типа хэндла (HBITMAP в данном случае) не дает никаких указаний на то, как он выделяется. Она может быть выделена с помощью всех механизмов, упомянутых выше.

Если предположить, что он создает HBITMAP с помощью GDI Object api функций (в частности, CreateBitmap функции), то для освобождения хэндла можно использовать DeleteObject функцию (согласно странице документации для GDI Object API функций).

8
ответ дан 3 December 2019 в 21:59
поделиться

Это зависит от ситуации. Есть ли у вас документация (или исходный код) для нативных функций, которые вы вызываете?

В нативном коде нет ни одной функции deallocation. Это одно из больших преимуществ CLR.

Если бы я делал ставки, я бы выбрал GlobalFree. Но будет не очень весело пробовать различные API, пока ваш код не перестанет падать.

2
ответ дан 3 December 2019 в 21:59
поделиться

Пожалуйста, покажите свой неуправляемый код. Существуют разные способы выделения памяти в неуправляемой области, и вы должны использовать соответствующие соответствующие средства освобождения. Вы, вероятно, в конечном итоге реализуете Finalizer и IDisposable и реализуете шаблон Dispose, как описано здесь: http://www.codeproject.com/KB/cs/idisposable.aspx

2
ответ дан 3 December 2019 в 21:59
поделиться

Как отмечают все остальные, это зависит от того, как он был выделен. Однако, если это действительно Win32 hbitmap, то вы деаллоцируете его с помощью функции Win32 "DeleteObject".

0
ответ дан 3 December 2019 в 21:59
поделиться

Возможно, вы могли бы попробовать создать объект Bitmap из hBitmap , а затем удалить его.

Bitmap bitmap = Bitmap.FromHBitmap(hBitmap);
bitmap.Dispose();
0
ответ дан 3 December 2019 в 21:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: