2010-12-17 47 views
3

並感謝任何幫助的建議。Interop的問題C#/ C:AccessViolationException

我在C這平凡函數:

__declspec(dllexport) Point* createPoint (int x, int y) { 
    Point *p; 

    p = (Point*) malloc(sizeof(Point)); 
    p->x = x; 
    p->y=y; 

    return p;  
} 

點是一個非常簡單的結構具有兩個int字段,x和y。

我想從C#調用這個函數。

我用這個代碼:

[DllImport("simpleC.dll", EntryPoint = "createPoint", CallingConvention = CallingConvention.Cdecl, SetLastError = true, CharSet = CharSet.Auto)] 
[return: MarshalAs(UnmanagedType.LPStruct)] 
public static extern Point createPoint(int x, int y); 

Point p = Wrapper.createPoint(1, 2); 

但在運行時我有一個AccessViolationException。詳細觀察異常,我發現從Marshal.CoTaskMemFree(IntPtr)方法拋出異常。

看來這種方法無法釋放C malloc分配的內存。

我在做什麼錯了?

真的很感謝。

回答

2

CoTaskMemFree不能用於釋放由malloc分配的內存(因爲它們使用不同的分配器)。根據​​,「運行時總是使用CoTaskMemFree方法釋放內存,如果您正在使用的內存沒有使用CoTaskMemAlloc方法分配,則必須使用IntPtr並使用適當的方法手動釋放內存。」

此外,Adam Nathan notes「UnmanagedType.LPStruct僅在一個特定情況下受支持:將System.Guid值類型視爲具有額外間接級別的非託管GUID ......您應該遠離UnmanagedType。 LPStruct。「

有兩種可能的解決方案:

  1. 聲明的方法IntPtr的返回類型和使用Marshal.ReadInt32閱讀結構的領域,或者使用Marshal.PtrToStructure將數據複製到一個管理結構,或使用不安全的代碼到IntPtr值轉換爲Point *,C庫將需要公開一個destroyPoint(Point *)方法釋放內存。
  2. 改變C方法簽名void getPoint(int x, int y, Point *),這讓C#分配的結構,而C方法簡單填充數據值(大部分是Win32 API是這樣定義的)。

最後一點:除非你的方法使用SetLastError的Win32 API,你不需要對你的P/Invoke屬性指定SetLastError = true

+0

非常感謝,您澄清我的任何想法!我的目標是將正則表達式的pcre C llibrary整合到C#中),然後返回很多malloc和sruct指針。 現在我正在使用第二種解決方案,它可以工作,但它很難釋放內存(應該寫C函數釋放器),但是我喜歡第二種解決方案,並且會實現它!非常感謝! – 2010-12-19 07:09:16

1

由於您沒有釋放「p」的代碼,所以很難說。然而,malloc()和free()在一起工作的方式很可能與C#管理內存的方式完全不同。由於C#有垃圾收集(我相信),它可能會使用完全不同的內存管理系統。

在任何情況下,正確的解決方案是,如果您使用庫創建對象,則還應該使用它來銷燬它。實現一個「destroyPoint」函數,釋放C庫中的內存,將其導入C#代碼,並從那裏調用它來銷燬由C庫創建的對象。

作爲一般的設計/編碼規則,每個「創建」函數應該有一個匹配的「自由/銷燬/刪除」功能。除此之外,它可以很容易地確保所有創建的項目得到適當的銷燬。

+0

非常感謝:) akk你給我的確認,從C分配的對象只能從其他C函數中釋放! – 2010-12-19 07:15:05

1

在C#端如何定義點類型?
它必須是不安全的,或者你需要返回一個void指針(IntPtr)。 GC不能計算來自外部的引用(這裏是分配的內存),因此您的代碼無法通過GC管理外部分配的內存。
一種替代方法是保持靜態引用以避免垃圾收集,如果您需要在應用程序的運行時期間持久保留該對象。

+0

嗨,感謝您的answare ...實際上我現在返回指針,然後在C#中我做出正確的演員。問題在於指針所引用的內存是不可分配的,除非是額外的C函數 – 2010-12-19 07:13:54