2009-06-15 73 views
1

我有這樣一段代碼(從諾基亞PC連接3.2示例代碼,在C#):運行「GC.Collect的」修復我的崩潰,但我不明白爲什麼

DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo = 
    new DAContentAccessDefinitions.CA_FOLDER_INFO(); 
    folderInfo.iSize = Marshal.SizeOf(folderInfo); //(32) 

    IntPtr bufItem = Marshal.AllocHGlobal(folderInfo.iSize); 

    //I often get a AccessViolationException on the following line 
    Marshal.StructureToPtr(folderInfo, bufItem, true); 

如果我在開始時運行GC.Collect(),然後我沒有收到AccessViolationException。但除非必要,否則我不想減慢此功能。我試過把GC.Keepalive放在不同的地方,但沒有成功。

CA_FOLDER_INFO被定義爲:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 
    public struct CA_FOLDER_INFO 
    { 
     public int iSize; 
     public int iFolderId; 
     public int iOptions; 
     public string pstrName; 
     public string pstrPath; 
     public int iSubFolderCount; 
     public IntPtr pSubFolders; 
     public IntPtr pParent; 
    } 

我不這樣做,在這種情況下,都要求使用字符串,並改變它們的定義,以IntPtr似乎使異常消失。

這是怎麼回事,防止異常的正確方法是什麼?

+4

不要忘記在一個try-finally包裝中,當你完成bufItem時調用Marshal.FreeHGlobal。 – sisve 2009-06-15 10:32:36

回答

5

你的問題是,你傳遞真實Marshal.StructureToPtr所以嘗試釋放兩個字符串指針(這有時是無效的)。您需要在此實例中傳遞false,因爲您只是在堆上分配了該內存。 (即沒有空閒空間)。

0

使用fixed關鍵字來獲取指向原始folderInfo的指針。

0

這可能是非託管資源不被釋放的東西。檢查你正在使用的任何東西是否實現IDisposable,如果是,則將其包裝在using { }塊中。

0

你確定Marshal.Sizeof(bufItem)和Marshal.Sizeof(folderInfo)是否一樣?

而且,也許事實上,你沒有初始化字符串?既然你說你在IntPtr(默認爲IntPtr.Zero)的時候沒有得到這個錯誤,那麼在嘗試編組緩衝區之前,我會嘗試設置它們以清空字符串。

[編輯]

也許你應該嘗試釘住緩衝處理,並封送處理的結構,而不是可見光反之亦然。事情是這樣的:

DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo; 

GCHandle pinnedHandle = GCHandle.Alloc(buffItem, GCHandleType.Pinned); 
folderInfo = (DAContentAccessDefinitions.CA_FOLDER_INFO)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(DAContentAccessDefinitions.CA_FOLDER_INFO)); 
pin.Free(); 

//folderInfo should contain the data from buffItem 
+1

將兩個字符串字段設置爲「」或String.Empty不會導致AccessViolationException消失... – Greg 2009-06-16 10:59:26

+1

尺寸相同。 – Greg 2009-06-16 11:00:00

相關問題