Навигация
Главная
Поиск
Форум
FAQ's
Ссылки
Карта сайта
Чат программистов

Статьи
-Delphi
-C/C++
-Turbo Pascal
-Assembler
-Java/JS
-PHP
-Perl
-DHTML
-Prolog
-GPSS
-Сайтостроительство
-CMS: PHP Fusion
-Инвестирование

Файлы
-Для программистов
-Компонеты для Delphi
-Исходники на Delphi
-Исходники на C/C++
-Книги по Delphi
-Книги по С/С++
-Книги по JAVA/JS
-Книги по Basic/VB/.NET
-Книги по PHP/MySQL
-Книги по Assembler
-PHP Fusion MOD'ы
-by Kest
Professional Download System
Реклама
Услуги

Автоматическое добавление статей на сайты на Wordpress, Joomla, DLE
Заказать продвижение сайта
Программа для рисования блок-схем
Инженерный калькулятор онлайн
Таблица сложения онлайн
Популярные статьи
OpenGL и Delphi... 65535
Форум на вашем ... 65535
HACK F.A.Q 65535
Бип из системно... 65535
Гостевая книга ... 65535
Invision Power ... 65535
Пример работы с... 65535
Содержание сайт... 65535
Организация зап... 65535
Вызов хранимых ... 65535
Создание отчето... 65535
Программируемая... 65535
Эмулятор микроп... 65535
Подключение Mic... 65535
Создание потоко... 65535
Приложение «Про... 65535
Оператор выбора... 65535
Модуль Forms 65535
ТЕХНОЛОГИИ ДОСТ... 63009
Имитационное мо... 58332
Реклама
Сейчас на сайте
Гостей: 5
На сайте нет зарегистрированных пользователей

Пользователей: 13,091
новичок: avegraf
Новости
Реклама
Выполняем курсовые и лабораторные по разным языкам программирования
Подробнее - курсовые и лабораторные на заказ
Delphi, Turbo Pascal, Assembler, C, C++, C#, Visual Basic, Java, GPSS, Prolog, 3D MAX, Компас 3D
Заказать программу для Windows Mobile, Symbian

Программа тестирования и обучающая программа по математике на Turbo Pasc...
Расчет размера дохода на одного человека в Turbo Pascal
Калькулятор на Delphi с переводом в другую систему исчисления + Блок схемы

Реклама



Подписывайся на YouTube канал о программировании, что бы не пропустить новые видео!

ПОДПИСЫВАЙСЯ на канал о программировании
Основы указателей



СОМ, подобно DCE (Distributed Computing Environment – среда распределенных вычислений), ведет свое начало от языка программирования С. Хотя лишь немногие разработчики используют С для создания или использования компонентов СОМ, именно от С СОМ унаследовала синтаксис для своего языка определений интерфейсов (Interface Definition Language – IDL). Одной из наиболее сложных проблем при разработке и использовании интерфейсов является управление указателями. Рассмотрим такое простое определение метода IDL:
HRESULT f([in] const short *ps);



Если бы вызывающая программа должна была запустить этот метод так:
short s = 10;
HRESULT hr = p->f(&s);



то величину 10 следовало бы послать объекту. Если бы этому методу нужно было выйти за границы апартамента, то интерфейсный заместитель был бы обязан разыменовать указатель и передать величину 10 в сообщение ORPC-запроса.
Следующий клиентский код, хотя и написан целиком в традициях С, представляет собой более интересный случай:
HRESULT hr = p->f(0);
// pass a null pointer
// передаем нулевой указатель



Если вызывающий поток выполняется в апартаменте объекта, то заместителя нет и нулевой указатель будет передан прямо объекту. Но что если объект расположен в другом апартаменте и заместитель используется? Что в точности должен передать интерфейсный заместитель, чтобы показать, что был послан нулевой указатель? Кроме того, означает ли это, что интерфейсные заместители и заглушки должны проверять каждый указатель, не является ли он нулевым? Оказывается, бывают ситуации, в которых указатель никогда не должен быть нулевым, и другие ситуации, когда нулевые указатели, наоборот, чрезвычайно полезны как начальные значения. В последнем случае факт передачи нулевого указателя интерфейсному заместителю должен быть продублирован интерфейсной заглушкой в апартаменте объекта.
Для того чтобы удовлетворить этим столь различным требованиям, СОМ позволяет разработчикам интерфейсов указывать точную семантику каждого параметра указателя. Чтобы показать, что указатель никогда не должен принимать нулевого значения, разработчик интерфейса может применить атрибут [ref]:
HRESULT g([in, ref] short *ps);
// ps cannot be a null ptr.
// ps не может быть нулевым указателем



Указатели, использующие атрибут [ref], называются ссылочными указателями (reference pointers). При IDL-определении, приведенном выше, следующий код со стороны клиента:
HRESULT hr = p->g(0);
// danger: passing null [ref] ptr.
// опасность: передается нулевой указатель с атрибутом [ref]



является ошибочным. И если p указывает на интерфейсный заместитель, то данный интерфейсный заместитель обнаружит нулевой указатель и возвратит вызывающей программе ошибку маршалинга, даже не передав метод текущему объекту. А чтобы сделать нулевой указатель допустимым значением параметра, в IDL-определении следует использовать атрибут [unique]:
HRESULT h([in, unique] short *ps);
// ps can be a null ptr.
// ps может быть нулевым указателем



Указатели, использующие атрибут [unique], называются уникальными указателями (unique pointers). При IDL-определении, приведенном выше, следующий код со стороны клиента:
HRESULT hr = p->h(0);
// relax: passing null [unique] ptr.
// расслабьтесь: передается нулевой указатель с атрибутом [unique]



является допустимым. Это означает, что интерфейсный заместитель должен подробно исследовать указатель перед тем, как разыменовать его. И что более важно: это означает, что интерфейсному заместителю необходимо записывать в ответ на ORPC-запрос не только разыменованную величину. Кроме нее, он должен записать тег, указывающий, был или не был передан нулевой указатель. Это добавляет к размеру ORPC-сообщения четыре байта на каждый указатель. Для большинства приложений эти добавочные четыре байта и то процессорное время, которое необходимо для выявления нулевого указателя [1] , пренебрежимо малы по сравнению с преимуществами использования нулевых указателей в качестве параметров.
Вообще говоря, схемы [ref] и [unique] мало отличаются по эффективности. Однако до сих пор не обсуждалась еще одна проблема, связанная с указателями. Рассмотрим следующий фрагмент на IDL:
HRESULT j([in] short *ps1, [in] short *ps2);



Имея такое IDL-определение, рассмотрим теперь следующий фрагмент кода со стороны клиента:
short x = 100;
HRESULT hr = p->j(&x, &х);
// note: same ptr. passed twice
// заметим: тот же самый указатель передан дважды



Естественный вопрос: что должен делать интерфейсный заместитель при наличии одинаковых указателей? Если интерфейсный заместитель не делает ничего, тогда значение 100 будет передано в ORPC-запросе дважды: один раз для *ps1 и один раз для *ps2. Это означает, что заместитель посылает одну и ту же информацию дважды, впустую занимая сеть и тем самым уменьшая ее пропускную способность. Конечно, число байтов, занятых величиной 100, невелико, но если бы ps1 и ps2 указывали на очень большие структуры данных, то повторная передача существенно повлияла бы на производительность. Другой побочный эффект от невыявления дублирующего указателя состоит в том, что интерфейсная заглушка будет демаршалировать эти значения в два различных места памяти. Если бы семантика метода изменилась из-за тождественности двух таких указателей:
STDMETHODIMP MyClass::j(short *ps1, short *ps2)
{
if (ps1 == ps2)
return this->OneKindOfBehavior(ps1);
else
return this->AnotherKindOfBehavior(ps1, ps2);
}



то интерфейсный маршалер нарушил бы семантический контракт (semantic contract) интерфейса, что нарушило бы прозрачность экспорта в СОМ.
Наличие атрибутов указателя [ref] и [unique] означает, что память, на которую ссылается указатель, не является ссылкой для какого-либо другого указателя в вызове метода и что интерфейсный маршалер не должен осуществлять проверку на дублирование указателей. Для того чтобы показать, что указатель может ссылаться на память, на которую ссылается другой указатель, разработчику IDL следует использовать атрибут [ptr]:
HRESULT k([in, ptr] short *ps1, [in, ptr] short *ps2);



Указатели, использующие атрибут [ptr], называются полными указателями (full pointers), потому что они наиболее близки к полному соответствию с семантикой языка программирования С. Имея такое IDL-определение, следующий код со стороны клиента:
short x = 100;
HRESULT hr = p->k(&x, &x);
// note: same ptr. passed twice
// заметим: тот же самый указатель передан дважды



передаст значение 100 ровно один раз, поскольку атрибут [ptr] при параметре ps1 сообщает интерфейсному маршалеру, что следует выполнить проверку на дублирование для всех остальных указателей с атрибутом [ptr]. Поскольку параметр ps2 также использует атрибут [ptr], интерфейсный маршалер определит значение дублирующего указателя [2] , а разыменует и передает значение только одного из указателей. Интерфейсная заглушка отметит, что это значение должно быть передано с обоими параметрами, ps1 и ps2, вследствие чего метод получит один и тот же указатель в обоих параметрах.
Хотя полные указатели могут решать различные проблемы и в определенных случаях полезны, они не являются предпочтительными указателями в семантике СОМ. Дело в том, что в большинстве случаев разработчик знает заранее, что дублирующие указатели передаваться не будут. Кроме того, поскольку полные указатели обеспечивают более короткие ORPC-сообщения в случае, если они являются дублирующими указателями, то расход ресурсов процессора на поиск дублирующих указателей может стать нетривиальным с ростом числа указателей на каждый метод. Если разработчик интерфейса уверен, что никакого дублирования не будет, то разумнее учесть это и использовать либо уникальные, либо ссылочные указатели.
Опубликовал Kest July 13 2009 17:37:23 · 0 Комментариев · 6717 Прочтений · Для печати

• Не нашли ответ на свой вопрос? Тогда задайте вопрос в комментариях или на форуме! •


Комментарии
Нет комментариев.
Добавить комментарий
Имя:



smiley smiley smiley smiley smiley smiley smiley smiley smiley
Запретить смайлики в комментариях

Введите проверочный код:* =
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Гость
Имя

Пароль



Вы не зарегистрированны?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Поделиться ссылкой
Фолловь меня в Твиттере! • Смотрите канал о путешествияхКак приготовить мидии в тайланде?
Загрузки
Новые загрузки
iChat v.7.0 Final...
iComm v.6.1 - выв...
Visual Studio 200...
CodeGear RAD Stud...
Шаблон для новост...

Случайные загрузки
Calendar
Основы Delphi
Borland Delphi 6....
Панель Наша Кнопка
AddPage [Исходник...
Самоучитель Прогр...
Язык программиров...
Архив значков
Page Promoter 7.7...
AdBlaster v2.5 - ...
JBlabel3D
TMS
WAP версия сайта
Ильдар Хабибуллин...
Игра змейка
Файловый менеджер
SynEdit
RxLIB
Assembler. Практикум
Crypt32

Топ загрузок
Приложение Клие... 100479
Delphi 7 Enterp... 87861
Converter AMR<-... 20082
GPSS World Stud... 13493
Borland C++Buil... 12055
Borland Delphi ... 8668
Turbo Pascal fo... 7048
Visual Studio 2... 5005
Калькулятор [Ис... 4908
FreeSMS v1.3.1 3545
Случайные статьи
Символы для формат...
Раскрутка блога в ...
Integer or real co...
транспортном режим...
Определить инициал...
Интерфейс аппаратн...
Поток с доступом к...
Планирование разве...
LINITIAL (ИНИЦИАЛИ...
Алгоритм замены ст...
Office 365 уже сег...
Классы и объекты D...
Модульность - МПролог
Содержание
1.4.3. Чтение и об...
Небольшие версии
Двоичные файлы
L2TP требует, чтоб...
Операторов typedef
Машинно-независима...
повлиять на развер...
Инструменты автома...
Работа с MySQL. Де...
SAVEVALUE (СОХРАНИ...
Как вставить в док...
Статистика



Друзья сайта
Программы, игры


Полезно
В какую объединенную сеть входит классовая сеть? Суммирование маршрутов Занимают ли таблицы память маршрутизатора?