Dies funktioniert:Wie marschiere ich zu ANSI-Zeichenfolge über Attribut?
[DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetError")]
private static extern IntPtr SDL_GetError();
public static string GetError()
{
return Marshal.PtrToStringAnsi(SDL_GetError());
}
Diese Abstürze:
[DllImport("SDL2.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetError")]
[return: MarshalAs(UnmanagedType.LPStr)]
public static extern string GetError();
This article schlägt vor, dass die Rückkehr Attribut ist im Wesentlichen wie Marshal.PtrToStringAnsi
nennen, so was ist der Deal?
Als Daniel pointed out, ist es wahrscheinlich abstürzt, weil der Einweiser den Speicher zu frei versucht. Der Artikel gibt auch an:
N.B. Beachten Sie, dass die nicht verwaltete Seite das Schlüsselwort "new" oder die C-Funktion "malloc()" nicht verwenden darf, um Speicher zuzuweisen. Der Interop Marshaler kann den Speicher in diesen Situationen nicht freigeben. Dies liegt daran, dass das Schlüsselwort "new" vom Compiler und die Funktion "malloc" von der C-Bibliothek abhängig ist.
Ich habe versucht, den char-Zeiger mit Marshal.FreeHGlobal
, Marshal.FreeCoTaskMem
und Marshal.FreeBSTR
befreien - sie alle zum Absturz bringen. Es gibt keine anderen Möglichkeiten, um den Speicher AFAIK zu befreien, also nehme ich an, dass der Speicher über new
oder malloc()
zugewiesen wurde. Also, was jetzt, ich bin eingesperrt? Ich habe ein permanentes Speicherleck in meinem Programm?
Ich überprüfte die Quelle. Die Zeichenfolge wird über static char errmsg[SDL_ERRBUFIZE]
erstellt. Mein C ist rostig, aber ich denke, es ist als static
deklariert, so dass es nicht freigegeben wird, wenn es den Funktionsumfang verlässt. Ich kann mich nicht erinnern, wo statische Arrays im Speicher landen. Gibt es einen Weg, sie zu befreien?
Bearbeiten: Warten ... es ist statisch. Das heißt, jedes Mal, wenn ein neuer Fehler auftritt, wird die alte Fehlermeldung überschrieben, weshalb SDL_GetError()
nur die letzte Fehlermeldung zurückgibt. Ergo, ich muss mich nicht darum kümmern, es zu befreien.
Als solche, wenn alle return: MarshalAs...
Optionen versuchen, den Speicher freizugeben, dann ist die einzige Lösung meine aktuelle. Dies ist schließlich optimal.
Ja, wenn es statisch ist, darf der Speicher nicht freigegeben werden. Die einzige Möglichkeit besteht darin, manuell zu marshallen, da sonst der CLR-Marshaller den Speicher freigibt. –