2014-07-01 55 views
2

實施例方法在IDL:我應該強制執行非參數爲非NULL嗎?

HRESULT _stdcall a_method([in] long value, [out] BSTR *comment); 

My功能的邏輯是,對於某些值,沒有註釋是必要的。如果客戶端使用comment == NULL調用此函數,我應該拋出異常嗎?或者可以寬容並容許這種情況?

(我正在用C++開發我的對象)。

我的努力嚴格要求的參數檢查的理由是,我很擔心內存泄漏,大約有客戶作出,根據COM規範,但我沒有對象接受呼叫是正確的來電。

+0

您是否期望使用'a_method'作爲RPC? –

+0

你的意思是,我是否期望在進程外服務器中使用它?目前我的服務器正在處理中,但我將來可能會開發一個oop版本。 –

回答

3

[out]參數的語義對此非常明確。

是得到一個[out]參數不應該的方法 - 不斷 - 看參數的值,直到它把東西就可以了。它是未初始化的內存。垃圾。事實上,如果你的方法是通過編組調用(inter-apartment或inter-process)來調用的,那麼垃圾就是你得到的:無論你的調用者在調用你的方法時可能放在哪裏,都被代理/存根;你永遠不會得到它。

如果客戶端/調用者在調用方法之前在參數上添加了某些內容,那肯定是內存泄漏(當然,它是一個像BSTR那樣的分配對象),但這是調用者的錯。所謂的方法不應該負責處理它。被調用的方法即使想要也不能處理泄漏。

如果要處理調用者可能傳入的任何值,則需要使用[in, out]參數而不是[out]

最後一次警告:自動化客戶端(VBA,VBScript等)不支持[out]參數。自動化將默默地處理任何[out]參數,如果它是[in, out],這使你在一個尷尬的境地:由客戶端應用程序被泄露放置在參數的任何值,你的方法不能做任何事情。

如果你計劃你的對象上正在使用的自動化客戶端,不使用[out]參數。改爲使用[in, out],並確保在調用之前,檢查調用者是否在參數上放置了一個值。代理/存根總是會爲[in, out]參數的兩種方式編組值。如果調用者在調用之前在參數上放置了一個值,則在寫入參數之前,您的方法負責釋放該值。

編輯:擴大對指針本身是NULL:

你能想到的檢查NULL,並返回E_INVALIDARG如果它是空的,但我不會推薦它。

是非法的傳遞NULL作爲用於[out]參數的指針值。即使您的代碼處理NULL值,如果調用被編組,編組人員也會觸發訪問衝突。編組人員必須在返回時訪問指向的值(將編組輸出存儲在其上),並且不會檢查null。

在您的特定情況下(調用語義是在給定情況下沒有任何內容可以返回),正確的過程是調用者始終提供一個指向存儲區的指針,並且調用的方法將值設置爲空值。像這樣:

// Caller 
BSTR comment; 
hr = obj->a_method(42, &comment); 

// Callee 
HRESULT a_method(value, BSTR *comment) 
{ 
    if (...) 
    { 
     //... I've decided we don't need to return a comment 
     *comment = NULL; 
    } 
    ... 
} 

如果你真的想要你提到的純空指針語義,你可以;但您必須使用[ptr]屬性標記該參數。據我所知,自動化客戶端不能很好地工作,你必須使用自定義編組器。如果您不希望使用自動化客戶端,這顯然是一種選擇。

+0

'ptr'呢? –

+0

作者:「自動化客戶端不支持'[out]'」,我認爲你不包括'[out,retval]' - 自動化支持哪一種? –

+0

@MattMcNabb,哦,我明白了;我誤解了你的問題的核心。我已經編輯了關於如何處理指針的更多細節。 @Jeffamaphone,是的,'[ptr]'會起作用。 –

相關問題