2009-10-22 40 views
3

我有一個DLL,它是用C++設計的,包含在一個C#項目中,我有奇怪的AccessViolationExceptions發生非理性。我懷疑我的垃圾收集不正確。我有一個非託管方法apiGetSettings(來自DLL),它應該將數據複製到Settings對象(實際上是原始代碼中的一個結構,但.NET InterOp只允許將數據作爲類對象導入,我使用System.Runtime.InteropServices。 Marshal方法來分配和釋放內存,但它可能會留下垃圾,導致所有內容崩潰c#interop marshalling and disposing

現在,我應該在Settings類中實現IDisposable方法嗎(如果是非託管的?)。如果是,我該如何處理字符串作爲編組和UnmanagedType.ByValTStr我要如何處置設置的對象?

using System.Runtime.InteropServices; 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
class Settings 
{ 
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 33)] 
internal string d; 
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 6)] 
internal string t; 
internal int b; 
} 

[DllImport(".\\foobar.dll", EntryPoint = "getSettings")] 
private static extern int apiGetSettings(IntPtr pointerToSettings); 

void GetSettings(ref Settings settings) 
{ 
int debug = 0; 

// Initialize a pointer for the structure and allocate memory 
IntPtr pointerToSettings = Marshal.AllocHGlobal(43); 

// Connect the pointer to the structure 
Marshal.StructureToPtr(settings, pointerToSettings, true); 

// Point the pointer 
debug = apiGetSettings(pointerToSettings); 

// Copy the pointed data to the structure 
Marshal.PtrToStructure(pointerToSettings, settings); 

// Free the allocated memory 
Marshal.FreeHGlobal(pointerToSettings); 
} 

回答

1

不,你並不需要實現IDisposable。您的設置類是管理類(這些attri butes僅用於運行時目的)並且將被垃圾收集。我的第一個猜測是:你分配了43個字節,但是你的字符串加起來超過了70個字節(記住,除非你是古老的Win98/Me,一個字符的大小是2個字節),所以你分配不夠。使用Marshal.SizeOf來動態確定結構的大小。

+0

謝謝你,我的救世主!否則我永遠不會想到這一點。這解決了我過去三個月以來的所有非理性問題。 :) – entro 2009-10-22 13:35:47