2011-06-09 43 views
2

我使用一些CComVariant類型變量來存儲接口pointers.However,有時我需要通過接口指針作爲NULL.In這種情況下,當我這樣做:VARIANT類型punkVal給出未定義的值?

CComVariant vAData,vBData; 
...... 
.... 
CComQIPtr<IBData> pAData = vAData.punkVal; //vAData is {0, VT_I4} when I pass NULL 

CComQIPtr<IBData>pBData = vBData.punkVal; //vBData is {0, VT_I4} when I pass NULL 

第一線失敗並引發異常,因爲在vAData.punkVal = 0xffffffff00000000 但第二行通過罰款沒有錯誤,它有有效vBData.punkVal值(0x0000000000000000)。

我想知道爲什麼兩個punkVal都不同時,當兩者都是空? 有沒有人知道爲什麼會發生這種情況? 僅在64位機器上拋出異常。

回答

3

CComVariant調用構造函數VariantInit()以及設定vtVT_EMPTY,但留下punkVal初始化(不讓它空)。

因爲您試圖構造一個CComQIPtr傳遞一個未初始化的指針,所以您嘗試執行的操作是未定義的行爲。

如果你想有一個CComVariant拿着一個空IUnknown*你可以這樣做:

CComVariant variant(static_cast<IUnknown*>(0)); // null IUnknown*, VT_UNKNOWN type 

現在是完全合法的,構建一個CComQIPtr

CComQIPtr<IWhatever> whatever(variant.punkVal); //punknVal is null - legal 
+0

我正在做這樣的事情:'CComVariant vAData,vBData; vAData = CComVariant(NULL); vBData = CCOMVariant(NULL); CComQIPtr pAData = vAData.punkVal; CComQIPtr pBData = vBData.punkVal;'所以punkval仍然是未初始化的? – Nikhil 2011-06-09 11:42:47

+0

兩種情況下,punkval都未初始化,但第一行失敗,第二行給出有效地址。 – Nikhil 2011-06-09 11:51:42

+0

@Nikhil:「未初始化」的意思是「你在那時得到的任何內容」。你真的關心爲什麼一個指針是空的而另一個不是? – sharptooth 2011-06-09 11:55:54

4

約變種一些額外的信息:他們有點奇怪,因爲它們是複合類型:它基本上是幾種類型的聯合,每種類型的字段(bstrVal,lVal,punkVal等)都佔據了內存中的相同空間,而vt字段指示哪個字段ld是有效的。

您應該只嘗試訪問匹配vt值的字段。所以如果vt是VT_BSTR,那麼只有bstrVal是有效的; punkVal是禁止的。如果vt是VT_I4,則只應使用lVal字段。

VT_EMPTY表示「此變體未設置爲任何值,因此不表示任何內容」;當vt是VT_EMPTY時,所有的字段都是禁止的 - 它們可能是之前發生的任何垃圾 - 這就是你在這裏看到的。

在Win64中,整數仍然是32位,但指針是64位。類型爲VT_I4且值爲0的變體將具有表示整數都設爲0的32位,但該變體中的其餘內存可能是任何剩餘垃圾。如果您試圖將該內存視爲一個64位指針 - 通過訪問punkVal - 那麼您將最終得到一個由這些32位構成的指針,而且還會從相鄰的32位未被正確初始化的指針 - 這可能是爲什麼你看到這兩種情況之間的差異。在Win32中,你會很幸運:指針與int的大小相同,所以如果你訪問一個爲0的VT_I4並讀取punkVal(你不應該!),你最終會得到一個NULL指針在這種情況下。