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



         

Указатели и память


Интерфейсы, показанные в данной главе до настоящего момента, были довольно просты и использовали только примитивные типы данных. При применении сложных типов данных одной из наиболее серьезных проблем является управление памятью для параметров метода. Рассмотрим следующий прототип функции IDL:

HRESULT f([out] short *ps);

При наличии такого прототипа нижеследующий код вполне допустим с точки зрения С:

short s; HRESULT hr = p->f(&s); // s now contains whatever f wrote // s теперь содержит все, что написал f

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

short *ps; // the function says it takes a short *, so ... // функция говорит, что она берет * типа short, следовательно ... HRESULT hr = p->f(ps);

При рассмотрении следующей допустимой реализации функции:

STDMETHODIMP MyClass::f(short *ps) { static short n = 0; *ps = n++; return S_OK; }

очевидно, что выделение памяти для короткого целого числа и передача ссылки на память в качестве аргумента функции является обязанностью вызывающей программы. О только что приведенной реализации заметим, что для функции неважно, откуда взялась эта память (например, динамически выделена из "кучи", объявлена как переменная auto в стеке), до тех пор, пока текущий аргумент ссылается на допустимую область памяти. Для подкрепления этого положения СОМ требует, чтобы все параметры с атрибутами [out], являющиеся указателями, были ссылочными указателями.

Ситуация становится менее очевидной, когда вместо простых целых типов используются типы, определенные пользователем. Рассмотрим следующее IDL-определение:

typedef struct tagPoint { short x; short у; } Point;

HRESULT g([out] Point *pPoint);

Как и в предыдущем примере, правильной является такая схема: вызывающая программа выделяет память для значений и передает ссылку на память, выделенную вызывающей программой:

Point pt; HRESULT hr = p->g(&pt);




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