2013-07-16 10 views
7

これは動作します:属性を使用してANSI文字列にマーシャリングする方法は?

[DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetError")] 
private static extern IntPtr SDL_GetError(); 

public static string GetError() 
{ 
    return Marshal.PtrToStringAnsi(SDL_GetError()); 
} 

このクラッシュ:

[DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetError")] 
[return: MarshalAs(UnmanagedType.LPStr)] 
public static extern string GetError(); 

This articleが戻り属性は、その契約何Marshal.PtrToStringAnsiを呼び出すような本質的であることを示唆していますか?ダニエルpointed outとして


マーシャラーがメモリを解放しようとしているので、それはおそらくクラッシュます。また、記事には、

N.B.注意:アンマネージ側は、メモリを割り当てるために、 "new"キーワードまたは "malloc()" C関数を使用してはいけません。 Interop Marshalerは、これらの状況でメモリを解放することはできません。これは、 "new"キーワードがコンパイラに依存し、 "malloc"関数がCライブラリに依存するためです。

私はMarshal.FreeHGlobalMarshal.FreeCoTaskMemMarshal.FreeBSTRとchar型のポインタを解放しようとした - 彼らはすべてのクラッシュ。メモリAFAIKを解放する他の方法はありませんので、メモリはnewまたはmalloc()で割り当てられたと思います。だから、今、私はフープですか?自分のプログラムに永久的なメモリリークがありますか?

ソースを確認しました。文字列はstatic char errmsg[SDL_ERRBUFIZE]で作成されます。私のCは錆びていますが、機能範囲から外れると解放されないように、staticと宣言されていると思います。私は静的な配列がどこにあるのか思い出せません。それらを解放する何らかの方法はありますか?

編集:待機...静的です。つまり、新しいエラーが発生するたびに古いエラーメッセージが上書きされるため、SDL_GetError()は最新のエラーメッセージのみを返します。エルゴ、私はそれを解放することについて心配する必要はありません。

このように、すべてのreturn: MarshalAs...オプションがメモリを解放しようとすると、唯一の解決策は現在の解決策です。結局、これは最適です。

+0

静的な場合は、メモリを解放してはいけません。唯一の方法は、手動でマーシャリングすることです。そうしないと、CLRマーシャラーがメモリを解放します。 –

答えて

3

私は少し掘りました。 SDL_GetErrorための源である:

const char * 
SDL_GetError(void) 
{ 
    static char errmsg[SDL_ERRBUFIZE]; 

    return SDL_GetErrorMsg(errmsg, SDL_ERRBUFIZE); 
} 

我々は、文字列のメモリが静的char配列として割り当てられていることを見ることができます。 SDL_GetErrorが呼び出されるたびに上書きされます。したがって、私たちはそれを解放する必要はありません。

[return: MarshalAs.*]のメソッドはすべて型をマーシャリングした後にメモリを解放しようとするため、機能しなくなり、さらにプログラムがクラッシュします。

このように、私のオリジナルの解決策が最適です。

4

リンクされた記事で述べたように、[return: MarshalAs(UnmanagedType.LPStr)]を使用すると、ネイティブ文字列のメモリは、FreeCoTaskMem()を使用してCLRによって解放されます。 Marshal.PtrToStringAnsi()で管理された文字列オブジェクトを手動で作成すると、メモリはまったく解放されません。

クラッシュした場合は、おそらく、CoTaskMemAlloc()を経由して管理されていない側ではなく、new()またはmalloc()などで文字列が作成された可能性があります。 SDL_GetError()のAPIには、そのジョブがネイティブ・ストリングを解放する方法とその方法を述べる必要があります。

関連する問題