В документации явно сказано, что QueryInterface, CoCreateInstance, DllGetClassObject и некоторые другие функции/методы в случае ошибки всегда возвращают нуль в переменную для адреса интерфейса. Однако, нигде не нашел утверждения о том, что это общее и обязательное правило. Зато обнаружил, что в коде многих COM-серверов это широко используется, и даже стоят assert'ы, проверяющие, чтобы при ошибке указатель всегда был нулевым.
Это просто добровольная страховка, или где-то установлено, как требование? Нужно ли при реализации COM-сервера всегда соблюдать это правило?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Это просто добровольная страховка, или где-то установлено, как требование? Нужно ли при реализации COM-сервера всегда соблюдать это правило?
Вот, например, в Delphi переменные-интерфейсы являются автоуправляемыми. Если после вызова QueryInterface в переменной окажется мусор, то при завершении процедуры (при выходе переменной из зоны видимости) будет автоматически вызван ее Release с последующим AV.
Re[2]: Правила возврата указателя и кода результата
Здравствуйте, Aniskin, Вы писали:
A>Вот, например, в Delphi переменные-интерфейсы являются автоуправляемыми. Если после вызова QueryInterface в переменной окажется мусор, то при завершении процедуры (при выходе переменной из зоны видимости) будет автоматически вызван ее Release с последующим AV.
Ну я по старой привычке всегда возвращал что-то в out-параметрах только при успешном завершении функции. В первом ответе (который ушел в мусор и, похоже, навсегда) говорится, что в COM это допустимо, но в исходниках от MS меня смутило обилие как явных присваиваний нуля в самом начале кода, так и финальных проверок на нуль при неудачном завершении.
Собственно, я этим озаботился после того, как уже две недели не могу понять, отчего граф DirectShow с моим фильтром падает при освобождении последней ссылки на IGraphBuilder или IMediaControl. Включил все отладочные сообщения в quartz.dll, но там все типично майкрософтовское — слов много, конкретных данных почти нет.
Вчера переделал код, чтобы везде записывал нули при неудаче, но граф все равно падает. Значит, проблема где-то еще.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>В документации явно сказано, что 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).
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Ну я по старой привычке всегда возвращал что-то в out-параметрах только при успешном завершении функции. В первом ответе (который ушел в мусор и, похоже, навсегда) говорится, что в COM это допустимо, но в исходниках от MS меня смутило обилие как явных присваиваний нуля в самом начале кода, так и финальных проверок на нуль при неудачном завершении.
Правило номер 0. Вызови SetErrorInfo(0,NULL);
Ну, кроме методов IUnknown
Правило номер 1. Инициализируй OUT-параметры перед тем как начинать работать. В том числе и перед проверкой допустимости значений аргументов.
Помнится, когда игрался с OutProc серверами, если не обнулять OUT-параметры, то падал код "маршаллинга" вызова методов интерфейса, который ложил на код возврата.
Соблюдай эти правила и сэкономишь кучу времени
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Правила возврата указателя и кода результата
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Вызови SetErrorInfo(0,NULL);
Хм, а что это даст? Я гляжу, эти функции как-то совсем непопулярны в народе и примерах от MS.
КД>Инициализируй OUT-параметры перед тем как начинать работать.
У меня была такая мысль, но в документации на этот счет ничего не нашел, а то ведь есть и такая парадигма, что OUT-параметры устанавливаются только при успешном завершении функции. Получается, в COM никто не вправе на это рассчитывать? Отдал параметр в функцию — потерял текущее значение?
Re[5]: Правила возврата указателя и кода результата
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>У меня была такая мысль, но в документации на этот счет ничего не нашел, а то ведь есть и такая парадигма, что 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[6]: Правила возврата указателя и кода результата
Здравствуйте, Евгений Музыченко, Вы писали:
КД>>Вызови SetErrorInfo(0,NULL);
ЕМ>Хм, а что это даст? Я гляжу, эти функции как-то совсем непопулярны в народе и примерах от MS.
Через ErrorInfo возвращается расширенное описание "результата" работы метода.
SetErrorInfo(0,NULL) зачищает мусор от предыдущих вызовов.
КД>>Инициализируй OUT-параметры перед тем как начинать работать.
ЕМ>У меня была такая мысль, но в документации на этот счет ничего не нашел, а то ведь есть и такая парадигма, что OUT-параметры устанавливаются только при успешном завершении функции.
Это экономия на спичках. Инициализируй всегда.
ЕМ>Получается, в COM никто не вправе на это рассчитывать? Отдал параметр в функцию — потерял текущее значение?
Не, ну есть общие правила. Но паранойя тут лишней не будет. Например, после S_OK из QueryInterface стоит проверить указатель на не NULL
У меня была одна бага — при OOM код сам себе "наступал на хвост" и возвращал S_OK+NULL. Я тогда на своей шкуре ощутил, что "устойчивость" кода это вполне реальная, а не абстрактная вещь
---
Не советую связываться с IN-OUT значениями. В большинстве случаев с ними одни проблемы.
Либо IN, либо OUT.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Это просто добровольная страховка, или где-то установлено, как требование? Нужно ли при реализации COM-сервера всегда соблюдать это правило?
Каждый православный COM интерфейс должен поддерживать IErrorInfo.
Только Путин, и никого кроме Путина! О Великий и Могучий Путин — царь на веки веков, навсегда!
Смотрю только Соловьева и Михеева, для меня это самые авторитетные эксперты.
КРЫМ НАШ! СКОРО И ВСЯ УКРАИНА БУДЕТ НАШЕЙ!
Re[2]: Правила возврата указателя и кода результата