これは動作します:属性を使用して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.FreeHGlobal
、Marshal.FreeCoTaskMem
とMarshal.FreeBSTR
とchar型のポインタを解放しようとした - 彼らはすべてのクラッシュ。メモリAFAIKを解放する他の方法はありませんので、メモリはnew
またはmalloc()
で割り当てられたと思います。だから、今、私はフープですか?自分のプログラムに永久的なメモリリークがありますか?
ソースを確認しました。文字列はstatic char errmsg[SDL_ERRBUFIZE]
で作成されます。私のCは錆びていますが、機能範囲から外れると解放されないように、static
と宣言されていると思います。私は静的な配列がどこにあるのか思い出せません。それらを解放する何らかの方法はありますか?
編集:待機...静的です。つまり、新しいエラーが発生するたびに古いエラーメッセージが上書きされるため、SDL_GetError()
は最新のエラーメッセージのみを返します。エルゴ、私はそれを解放することについて心配する必要はありません。
このように、すべてのreturn: MarshalAs...
オプションがメモリを解放しようとすると、唯一の解決策は現在の解決策です。結局、これは最適です。
静的な場合は、メモリを解放してはいけません。唯一の方法は、手動でマーシャリングすることです。そうしないと、CLRマーシャラーがメモリを解放します。 –