J
jsendrow
Ein IntPtr gibt den Speicher nicht frei, auf den er zeigt. Wird er also geGCt wird lediglich sein eigener Speicher freigegeben, nicht der auf den er sozusagen zeigt. Von daher gesehen kann die GC einen Handle, der in einen IntPtr gepackt wurde nicht freigeben (im Gegensatz zu SafeHandle, das genau dafür konzipiert wurde).
es geht aber nicht um das Freigeben sondern darum, das die GC auch Speicher defragmentiert, was konkret bedeutet das Objekte auf dem Heap herumgeschoben werden können. Reicht man nun eine Variable/Zeiger aus einem Managed Objekt runter in eine native Funktion und die GC verschiebt das managed Objekt _bevor_ die native Funktion beendet, dann ist die Variable/Zeiger der nativen Funktion nicht mehr gültig -> Stack bzw heap Korruption. Dies gilt übrigends auch für variablen die by Value übergeben werden, auch wenn man das auf den ersten Blick nicht erwarten würde.
Also sowas wie:
Code:
void managed_function()
{
int wert = 5;
unmanaged_function(wert); // kann heap corruption erzeugen
}
sollte eigendlich lauten:
Code:
void managed_function()
{
int wert = 5;
pin_ptr<int> pinnedWert = &wert;
unmanaged_function(*pinnedWert); // sicher
}
Das dumme an diesem Fehler ist, daß man zu 99% damit durchkommt weil er nur dann auftritt wenn die GC zufällig zum richtigen Zeitpunkt läuft um den Fehler zu verursachen... Die Fehlerhäufigkeit steigt meist mit der Anzahl der GC-Läufe.