Подтвердить что ты не робот

Использование CoTaskMemAlloc?

Когда целесообразно использовать CoTaskMemAlloc? Может ли кто-нибудь привести пример?

4b9b3361

Ответ 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()