Re[5]: Правила возврата указателя и кода результата
От: Conr Россия  
Дата: 29.08.19 12:22
Оценка: 13 (2)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>У меня была такая мысль, но в документации на этот счет ничего не нашел, а то ведь есть и такая парадигма, что OUT-параметры устанавливаются только при успешном завершении функции. Получается, в COM никто не вправе на это рассчитывать? Отдал параметр в функцию — потерял текущее значение?

Это неправильная парадигма. В случае ошибки все out параметры обязательно должны быть выставлены в NULL.
The Rules of the Component Object Model, Memory Management Rules:

If a function returns a failure code, then in general the caller has no way to clean up the out or in-out parameters. This leads to a few additional rules:

— In error returns, out parameters must always be reliably set to a value that will be cleaned up without any action on the caller's part.

Further, it is the case that all out pointer parameters (including pointer members of a caller-allocate callee-fill structure) must explicitly be set to NULL. The most straightforward way to ensure this is (in part) to set these values to NULL on function entry.

— In error returns, all in-out parameters must either be left alone by the callee (and thus remaining at the value to which it was initialized by the caller; if the caller didn't initialize it, then it's an out parameter, not an in-out parameter) or be explicitly set as in the out parameter error return case.


Более свежей документации под рукой нет, хорошо хоть эта сохранилась..
Re[5]: Правила возврата указателя и кода результата
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 29.08.19 13:48
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

КД>>Вызови SetErrorInfo(0,NULL);


ЕМ>Хм, а что это даст? Я гляжу, эти функции как-то совсем непопулярны в народе и примерах от MS.


Через ErrorInfo возвращается расширенное описание "результата" работы метода.

SetErrorInfo(0,NULL) зачищает мусор от предыдущих вызовов.

КД>>Инициализируй OUT-параметры перед тем как начинать работать.


ЕМ>У меня была такая мысль, но в документации на этот счет ничего не нашел, а то ведь есть и такая парадигма, что OUT-параметры устанавливаются только при успешном завершении функции.


Это экономия на спичках. Инициализируй всегда.

ЕМ>Получается, в COM никто не вправе на это рассчитывать? Отдал параметр в функцию — потерял текущее значение?


Не, ну есть общие правила. Но паранойя тут лишней не будет. Например, после S_OK из QueryInterface стоит проверить указатель на не NULL

У меня была одна бага — при OOM код сам себе "наступал на хвост" и возвращал S_OK+NULL. Я тогда на своей шкуре ощутил, что "устойчивость" кода это вполне реальная, а не абстрактная вещь

---
Не советую связываться с IN-OUT значениями. В большинстве случаев с ними одни проблемы.

Либо IN, либо OUT.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Правила возврата указателя и кода результата
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 19.08.19 20:50
Оценка:
В документации явно сказано, что QueryInterface, CoCreateInstance, DllGetClassObject и некоторые другие функции/методы в случае ошибки всегда возвращают нуль в переменную для адреса интерфейса. Однако, нигде не нашел утверждения о том, что это общее и обязательное правило. Зато обнаружил, что в коде многих COM-серверов это широко используется, и даже стоят assert'ы, проверяющие, чтобы при ошибке указатель всегда был нулевым.

Это просто добровольная страховка, или где-то установлено, как требование? Нужно ли при реализации COM-сервера всегда соблюдать это правило?
код результат hresult указатель адрес нуль null
Re: Правила возврата указателя и кода результата
От: Aniskin  
Дата: 19.08.19 23:34
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Это просто добровольная страховка, или где-то установлено, как требование? Нужно ли при реализации COM-сервера всегда соблюдать это правило?


Вот, например, в Delphi переменные-интерфейсы являются автоуправляемыми. Если после вызова QueryInterface в переменной окажется мусор, то при завершении процедуры (при выходе переменной из зоны видимости) будет автоматически вызван ее Release с последующим AV.
Re[2]: Правила возврата указателя и кода результата
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 20.08.19 09:31
Оценка:
Здравствуйте, Aniskin, Вы писали:

A>Вот, например, в Delphi переменные-интерфейсы являются автоуправляемыми. Если после вызова QueryInterface в переменной окажется мусор, то при завершении процедуры (при выходе переменной из зоны видимости) будет автоматически вызван ее Release с последующим AV.


Ну я по старой привычке всегда возвращал что-то в out-параметрах только при успешном завершении функции. В первом ответе (который ушел в мусор и, похоже, навсегда) говорится, что в COM это допустимо, но в исходниках от MS меня смутило обилие как явных присваиваний нуля в самом начале кода, так и финальных проверок на нуль при неудачном завершении.

Собственно, я этим озаботился после того, как уже две недели не могу понять, отчего граф DirectShow с моим фильтром падает при освобождении последней ссылки на IGraphBuilder или IMediaControl. Включил все отладочные сообщения в quartz.dll, но там все типично майкрософтовское — слов много, конкретных данных почти нет.

Вчера переделал код, чтобы везде записывал нули при неудаче, но граф все равно падает. Значит, проблема где-то еще.
Re: Правила возврата указателя и кода результата
От: Vi2 Удмуртия http://www.adem.ru
Дата: 20.08.19 16:54
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>В документации явно сказано, что QueryInterface, CoCreateInstance, DllGetClassObject и некоторые другие функции/методы в случае ошибки всегда возвращают нуль в переменную для адреса интерфейса. Однако, нигде не нашел утверждения о том, что это общее и обязательное правило. Зато обнаружил, что в коде многих COM-серверов это широко используется, и даже стоят assert'ы, проверяющие, чтобы при ошибке указатель всегда был нулевым.


ЕМ>Это просто добровольная страховка, или где-то установлено, как требование? Нужно ли при реализации COM-сервера всегда соблюдать это правило?


Для методов интерфейсов, например, IUnknown::QueryInterface, это положение обязательно и описывается атрибутом [out]. Предполагается, что значение параметра не определено при входе в метод и должно быть установлено на выходе.

Некоторые смарт-пойнтеры в реализации operator& принудительно сбрасывают своё содержимое или генерят исключение перед возвратом адреса — как раз для этого случая.

Остальные функции придерживаются аналогичного соглашения уже по аналогии или по тому, что передают эти выходные параметры в реальный интерфейс.

Например, WINOLEAPI CoCreateInstance(IN REFCLSID rclsid, IN LPUNKNOWN pUnkOuter, IN DWORD dwClsContext, IN REFIID riid, OUT LPVOID * ppv); передаёт свой параметр ppv в функцию CreateInstance интерфейса IClassFactory: pCF->CreateInstance(pUnkOuter, riid, ppvObj).
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[3]: Правила возврата указателя и кода результата
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 29.08.19 08:17
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Ну я по старой привычке всегда возвращал что-то в out-параметрах только при успешном завершении функции. В первом ответе (который ушел в мусор и, похоже, навсегда) говорится, что в COM это допустимо, но в исходниках от MS меня смутило обилие как явных присваиваний нуля в самом начале кода, так и финальных проверок на нуль при неудачном завершении.


Правило номер 0. Вызови SetErrorInfo(0,NULL);

Ну, кроме методов IUnknown

Правило номер 1. Инициализируй OUT-параметры перед тем как начинать работать. В том числе и перед проверкой допустимости значений аргументов.

Помнится, когда игрался с OutProc серверами, если не обнулять OUT-параметры, то падал код "маршаллинга" вызова методов интерфейса, который ложил на код возврата.

Соблюдай эти правила и сэкономишь кучу времени
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Правила возврата указателя и кода результата
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.08.19 11:40
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вызови SetErrorInfo(0,NULL);


Хм, а что это даст? Я гляжу, эти функции как-то совсем непопулярны в народе и примерах от MS.

КД>Инициализируй OUT-параметры перед тем как начинать работать.


У меня была такая мысль, но в документации на этот счет ничего не нашел, а то ведь есть и такая парадигма, что OUT-параметры устанавливаются только при успешном завершении функции. Получается, в COM никто не вправе на это рассчитывать? Отдал параметр в функцию — потерял текущее значение?
Re[6]: Правила возврата указателя и кода результата
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 29.08.19 13:31
Оценка:
Здравствуйте, Conr, Вы писали:

C>The Rules of the Component Object Model, Memory Management Rules


О, спасибо. Что-то в этом роде я искал, но как-то прошел мимо.
Re: Правила возврата указателя и кода результата
От: Мёртвый Даун Россия  
Дата: 11.12.19 08:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Это просто добровольная страховка, или где-то установлено, как требование? Нужно ли при реализации COM-сервера всегда соблюдать это правило?


Каждый православный COM интерфейс должен поддерживать IErrorInfo.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re[2]: Правила возврата указателя и кода результата
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.12.19 09:23
Оценка:
Здравствуйте, Мёртвый Даун, Вы писали:

МД>Каждый православный COM интерфейс должен поддерживать IErrorInfo.


Какова связь этого утверждения с заданным вопросом?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.