Сущность технологии COM



         

Указатели и память - часть 4


HUMAN bob = { 2231 }; DOG fido = { 12288, &bob }; // fido is owned by bob // fido принадлежит bob'y HRESULT hr = p->TakeToGroomer(&fido); // this is correct! // это правильно!

В то же время разграничение между указателями высшего уровня и вложенными является существенным, когда оно касается организации памяти для параметров [out] и [in,out]. Для обоих параметров, [out] и [in,out], память, на которую ссылаются указатели высшего уровня, управляется вызывающим оператором, как и в случае параметров [in]. Для вложенных же указателей, которые появляются в параметрах [out] и [in, out], память управляется вызываемым оператором (самим методом). Причина появления этого правила заключается в том, что глубина вложения типов данных может быть сколь угодно большой. Например, в таком определении типа:

typedef struct tagNODE { short value; [unique] struct tagNODE *pNext; } NODE:

вызывающему оператору невозможно заранее определить, сколько подэлементов понадобится разместить. Однако, поскольку вызываемый оператор (данный метод) будет снабжать данными каждый узел, он благополучно может выделить память для каждого необходимого узла.

При наличии правила, по которому разработчики метода должны выделять память при инициализации любых вложенных указателей, возникает естественный вопрос, откуда методы должны получить эту память, чтобы вызывающие операторы знали, как освободить ее после прочтения всех возвращенных значений? Ответом является распределитель памяти (task allocator) СОМ-задачи. Распределителем памяти задачи СОМ называется распределитель памяти, индивидуальный для каждого процесса, используемый исключительно для выделения памяти вложенным указателям с атрибутами [out] и [in,out]. Проще всего использовать этот распределитель памяти СОМ-задачи посредством применения трех API-функций СОМ:

void *CoTaskMemAlloc(DWORD cb); // allocate cb bytes // размещаем cb байтов void CoTaskMemFree(void *pv); // deallocate memory at *pv // освобождаем память в *pv void *CoTaskMemRealloc(void *pv,DWORD cb); // grow/shrink *pv // расширяем/сжимаем *pv




Содержание  Назад  Вперед