Посмотрите на правило с точки зрения упорядоченного вызова (то есть того, что происходит, когда объект находится в другом подразделении COM или когда он находится в другом процессе или машине); вы поймете, как работает это правило и почему это единственное разумное правило, которое может существовать.
Ключевым фактом является то, что для параметра [out]
маршаллер не маршалирует начальное значение вызываемому объекту.
Это означает, что не имеет значения, что вы поместите в переменную перед выполнением вызова. Это может быть мусор или NULL. Никто не собирается на это смотреть.
Примечание. Это также означает, что если перед вызовом переменная содержит что-то, что нужно освободить, вы должны сами освободить это перед вызовом, иначе произойдет утечка. Маршаллер не собирается выпускать его для вас (потому что, будучи параметром [out]
, маршаллер должен считать его мусором), а вызываемый объект не может освободить его, даже если захочет (потому что он никогда не получит существующее значение от машаллер).< /эм>
Во-вторых, после возврата вызова вызываемый не может узнать, что вы делаете с возвращаемым значением, поэтому единственный, кто может освободить параметр, — это вызывающий.
Ситуация с условиями ошибки немного сложнее.
В принципе, COM требует, чтобы параметр [out]
был установлен в согласованное ("marshallable"?) значение перед возвратом (либо NULL, либо его эквивалент, либо допустимое значение), даже при наличии ошибки. Это также «единственное разумное правило»: маршаллер не может знать, что вызываемый объект находится в ситуации ошибки. Он также не будет угадывать на основе HRESULT, потому что даже HRESULT «класса ошибок» не означает, что метод не намеревается возвращать значения вызывающей стороне. Маршаллер собирается передать значение параметра обратно вызывающему объекту (с ошибкой или без ошибки), поэтому лучше, чтобы параметр был действительным, иначе сам маршаллер выйдет из строя.
На практике... ну, некоторые объекты написаны лучше, чем другие, а некоторые COM-классы никогда не вызываются через сортировку, поэтому разработчики класса никогда не обнаруживают проблему. Класс, который не соответствует этим правилам, нельзя безопасно использовать в квартирах.
Канонический способ убедиться, что значения параметра остаются согласованными даже в случае ошибки, выглядит примерно так:
STDMETHODIMP Class::Method(BSTR *pValue)
{
*pValue = NULL; // 1) Initialize all the [out] parameters before
// doing anything, to make sure they are always
// consistent
BSTR tempValue; // 2) Use a temporary to hold any result value
... // 3) Use the temporary for all computations
... // Finish all other processing
*pValue = tempValue; // 4) Only after all possible error conditions
// are behind us, do put the new value
// in the output parameter
return S_OK;
}
Очевидно, что если выходной параметр — это просто значение, которое не нужно освобождать (например, int и т. д.), то все это не имеет значения.
person
Euro Micelli
schedule
07.06.2013