Когда целесообразно использовать CoTaskMemAlloc? Может ли кто-нибудь привести пример?
Использование CoTaskMemAlloc?
Ответ 1
Гоша, мне пришлось немного подумать об этом - я сделал небольшое количество небольших программ COM с ATL и редко использовал его.
Существует одна ситуация, которая приходит на ум: Расширения Windows Shell. Если вы имеете дело с набором объектов файловой системы, вам, возможно, придется иметь дело с PIDLs (указатель на список идентификаторов). Это причудливые небольшие абстракции объектов файловой системы, и они должны быть явно выделены/освобождены с использованием диспетчера с поддержкой COM, такого как CoTaskMemAlloc
. Существует также альтернатива, указатель интерфейса IMalloc
, полученный из SHGetMalloc
(устаревший) или CoGetMalloc
- это просто уровень абстракции чтобы ваш код не был привязан к определенному распределителю памяти и может использовать любой подходящий.
Точка использования CoTaskMemAlloc
или IMalloc
, а не malloc()
заключается в том, что выделение/освобождение памяти должно быть чем-то вроде "COM-aware", чтобы его распределение и освобождение выполнялись последовательно во время выполнения, даже если выделение и освобождение выполняются полностью несвязанным кодом (например, Windows выделяет память, переносит ее на ваш код на С++, который позже освобождается, или ваш код на С++ выделяет, передает его кому-то другому коду VB, который позже освобождается). Ни malloc()
, ни new
не способны взаимодействовать с кучей времени выполнения системы, поэтому вы не можете использовать их для распределения памяти для передачи на другие COM-объекты или для приема памяти из других COM-объектов и освобождения.
Ответ 2
Используйте CoTaskMemAlloc при возврате char * из собственной библиотеки С++ в .NET в виде строки.
С#
[DllImport("test.dll", CharSet=CharSet.Ansi)]
extern static string Foo();
С
char* Foo()
{
std::string response("response");
int len = response.length() + 1;
char* buff = (char*) CoTaskMemAlloc(len);
strcpy_s(buff, len, response.c_str());
return buff;
}
Так как .NET использует CoTaskMemFree, вам необходимо выделить такую строку, вы не можете выделить ее в стек или кучу, используя malloc/new.
Ответ 3
В этой статье MSDN сравниваются несколько различных распределителей, открытых Win32, включая CoTaskMemAlloc. Он в основном используется в программировании COM - особенно когда реализация COM-сервера должна выделять память для возврата обратно клиенту. Если вы не пишете COM-сервер, вам, вероятно, не нужно его использовать.
(Тем не менее, если вы вызываете код, который выделяет память с помощью CoTaskMemAlloc и возвращает его обратно вам, вам нужно освободить возвращенное выделение с помощью CoTaskMemFree.)
Ответ 4
CoTaskMemAlloc такой же, как malloc, за исключением того, что прежний используется для выделения памяти, которая используется через границы процесса.
i.e., если у нас есть два процесса, process1 и process2, предположим, что process1 является COM-сервером, а process2 - COM-клиентом, который использует интерфейсы, открытые процессом1. Если process1 должен отправить некоторые данные, он может выделить память, используя CoTaskMemAlloc, чтобы выделить память и скопировать данные. Доступ к этой ячейке памяти можно получить через process2.
Библиотека COM автоматически выполняет сортировку и разборку.
Ответ 5
на самом деле не так много, что может пойти не так, потому что следующие вызовы все имеют одинаковое распределение:
CoTaskMemAlloc/SHAlloc -> IMalloc.Alloc -> GlobalAlloc(GMEM_FIXED)
только если вы используете не-windows (компилятор-библиотеку), такие как malloc()
, все будет не так.
Официально для COM-вызовов следует использовать CoTaskMemAlloc
(например, выделить поле FORMATETC.ptd)
То, что CoTaskMemAlloc
равно GlobalAlloc()
, останется таким образом ", пока вечность не увидится в буфере обмена api и com STGMEDIUM. STGMEDIUM использует структуры и метод буфера обмена, и хотя STGMEDIUM является com и, таким образом, CoTaskMemAlloc, буфер обмена apis предписывает GlobalAlloc()