Будет ли использование MarshalAs (UnmanagedType.LPWStr) очищать память? - PullRequest
7 голосов
/ 20 ноября 2011

Я пытаюсь написать pinvoke для метода ITaskTrigger :: GetTriggerString (определен в http://msdn.microsoft.com/en-us/library/windows/desktop/aa381866(v=vs.85).aspx). Если вы посмотрите на страницу, он говорит, что вызывающий метод отвечает за освобождение памяти (через CoTaskMemFree) LPWSTR, на который ссылается первый аргумент. Хотя я мог сделать это вручную в .NET или написать свой собственный маршалер с помощью ICustomMarshaler, мне было интересно, освободит ли память использование атрибута MarshalAs (UnmanagedType.LPWStr) для этого конкретного аргумента соответственно.

Может ли кто-нибудь дать некоторое представление?

1 Ответ

6 голосов
/ 20 ноября 2011

Перво-наперво: вы здесь говорите о COM Interop (ITaskTrigger - это интерфейс COM), а не P / Invoke.Для них существуют разные правила взаимодействия, поэтому важно, чтобы они были прямыми.Например, вам нужно определить оболочки взаимодействия C # для всего интерфейса, а не только для нужного вам метода.Это должно помочь вам начать: pinvoke.net

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

Более длинный ответ включает в себя различные типы сортировки кода взаимодействия COM, в зависимости от типов параметров, направлений и того, какие атрибуты вы добавляете в сигнатуры взаимодействия.

В этом случаеТип параметра, который вы получите при вызове, является параметром "out string" с атрибутом MarshalAs(UnmanagedType.LPWSTR).Когда COM-сервер предоставляет вызов с параметром «out» строкового типа LPWSTR, предполагая, что сервер поддерживает свое окончание сделки, он выделит буфер памяти с CoTaskMemAlloc() и вернет его вам.(Если бы это был другой тип строки, например BSTR, конкретный вызов выделения памяти мог бы быть другим, но основная концепция та же.) На этом этапе вы несете ответственность за очистку этой памяти, когда вам больше не нужноэто, используя соответствующий вызов CoTaskMemFree().

Это специальный тип операции, называемый «изменением ссылки»: отправляемый параметр уже является ссылочным параметром, но COM-сервер собирается заменить на отличается ссылка.Хорошее объяснение этого процесса можно найти в разделе «Владение памятью» этой статьи журнала MSDN .Как вы можете видеть из этой статьи, когда CLR получает данные от параметра «out» для ссылочного типа, он признает, что берет на себя ответственность за освобождение этой памяти.При маршалинге этого обратного вызова к управляемому коду он использует атрибут MarshalAs, чтобы определить, что это указатель LPWSTR в виде строки в COM, и что поэтому он должен быть выделен с использованием CoTaskMemAlloc().После создания управляемой строки из данных она вызовет CoTaskMemFree() в исходном буфере от вашего имени.Полученные вами данные будут полностью обработаны, и вам не придется иметь дело с какими-либо проблемами владения.

...