2012-07-04 57 views
1

我正在與需要獲取的第三方庫進行通信,並且發佈了非託管資源。經過一番閱讀後,我得出結論:管理資源參考的最佳和「正確」方式是在SafeHandleCriticalHandle對象中。將未簽名的短整理爲SafeHandle

我的問題出現了,因爲第三方庫返回的句柄是無符號短數字值而不是指針。如果我在返回的句柄上指定MarshalAsAttribute,我會得到一個MarshalDirectiveException(CriticalHandles必須沒有MarshalAs屬性集並且不能在數組中使用)。

這裏是我考慮過的事情:

  • 元帥手柄在他們的數字格式,並通過Criticalhandle.SetHandle方法在CriticalHandle包裝他們。如果在獲取引用和封裝它之間發生異常,這就允許潛在的泄漏句柄。
  • 以其數字格式編組並存儲句柄。有含型的工具CriticalFinalizerObject。如果在獲取引用和封裝它之間發生異常,這就允許潛在的泄漏句柄。
  • 將手柄編成SafeHandle作爲IntPtr(讓最重要的2個字節填充準垃圾)。每次我需要調用SafeHandle的本地方法時,將DangerousGetHandle簡化爲簡短(丟棄最重要的2個字節的垃圾)。這將防止手柄的任何潛在泄漏,但是非常麻煩,並且具有使用暴力破壞錯誤解決方案的外觀。

我應該如何處理這些'手柄'?

+1

如果您的本機代碼是32位,則可以使SafeHandle正常工作。在C或C++函數調用中,一個簡短參數總是被提升爲int。 IntPtr不會混淆它。 –

+0

這讓我放心,但這讓我想知道爲什麼額外的數據有時會填充到返回值中最重要的2個字節中。 IE:有時高2字節包含所有0的位模式,其他時間包含0x0091的位模式。雖然我知道導致這兩種情況的場景,但我不知道額外的比特代表什麼。也許這是我應該調查的特定於我的圖書館的內容。謝謝。 –

+0

@HansPassant這對我來說非常好。你可以張貼這個答案,以便我可以接受它嗎? –

回答

1

正如@HansPassant提到的對我的問題發表評論stion:

如果您的本地代碼是32位,則可以使SafeHandle正常工作。在C或C++函數調用中,一個簡短的 參數總是被提升爲int。 IntPtr不會混淆它。 - Hans Passant Jul 4 at 15:10

因此可以將C/C++無符號短直接編組爲SafeHandle的派生值。

2

我覺得在這裏做正確的事情就是實現類似SafeHandle(從CriticalFinalizerObject得出自己的包裝,然後包裝來電轉接到您的P/Invoke創建一個constrained execution region handle方法,以確保管理手柄包裝是正確初始化

注意:我還沒有收到使用CER,所以無需驗資我只能希望這個代碼提供了一個起點

[DllImport("blah.dll")] 
private static extern ushort CreateMySpecialHandle(); 

public static SafeSpecial Handle Foo() 
{ 
    SafeSpecialHandle safeHandle = new SafeSpecialHandle(); 
    System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); 
    try 
    { 
    } 
    finally 
    { 
     ushort rawHandle = CreateMySpecialHandle(); 
     safeHandle.SetHandle(rawHandle); 
    } 

    if (safeHandle.IsInvalid) 
    { 
     // throw exception here, or other error handling 
    } 

    return safeHandle; 
} 
+0

我讀過這篇文章,但對於什麼被認定爲'帶外'異常還沒有確定。如果沒有這個,我無法確定是否有'CreateMySpecialhandle()'會執行並獲得一個句柄,但沒有保存在'SafeHandle'中的場景。 –

+0

這個例子似乎被幾乎相同的代碼片段所強化,其中包含了MSDN ['RuntimeHelpers.PrepareConstrainedRegions']中的附加信息(http://msdn.microsoft.com/zh-cn/library/system.runtime.compilerservices.runtimehelpers .prepareconstrainedregions.aspx)方法文檔。 –