Ausführen eines ‚GC.Collect‘ behebt meinen Absturz, aber ich verstehe nicht, warum
Frage
Ich habe dieses Stück Code (aus dem Nokia PC Connectivity 3.2 Beispielcode in C #):
DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo =
new DAContentAccessDefinitions.CA_FOLDER_INFO();
folderInfo.iSize = Marshal.SizeOf(folderInfo); //(32)
IntPtr bufItem = Marshal.AllocHGlobal(folderInfo.iSize);
//I often get a AccessViolationException on the following line
Marshal.StructureToPtr(folderInfo, bufItem, true);
Wenn ich GC.Collect()
zu Beginn dieses laufen, dann erhalte ich keine AccessViolationException
. Aber ich mag diese Funktion nicht verlangsamen, wenn nicht erforderlich. Ich habe GC.Keepalive
an verschiedenen Orten versucht setzen, aber ohne Erfolg.
CA_FOLDER_INFO
ist definiert als:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CA_FOLDER_INFO
{
public int iSize;
public int iFolderId;
public int iOptions;
public string pstrName;
public string pstrPath;
public int iSubFolderCount;
public IntPtr pSubFolders;
public IntPtr pParent;
}
Ich weiß nicht, in diesem Fall benötigen Sie eine der Saiten, und ihre Definitionen zu IntPtr
Veränderung scheint die Ausnahme zu machen geht weg.
Was ist hier los ist, und was ist der richtige Weg, um die Ausnahme zu verhindern?
Lösung
Ihr Problem ist, dass Sie Marshal.StructureToPtr wahr vorbei sind, so dass es die beiden String-Zeiger zu befreien versucht (die manchmal sind ungültig). Sie müssen in diesem Fall falsch passieren, da Sie nur, dass der Speicher auf dem Heap zugeordnet. (Das heißt, es gibt nichts, was es zu befreien).
Andere Tipps
Sind Sie sicher, Marshal.SizeOf (bufItem) und Marshal.SizeOf (Folder) gleich sind?
Und vielleicht die Tatsache, dass Sie nicht die Saiten initialisiert wird? Da Sie sagen, dass Sie nicht den Fehler, wenn sie IntPtr (welche standardmäßig IntPtr.Zero) sind, würde ich versuchen, sie beide zu leere Saiten einstellen, bevor Sie das Pufferfeld versuchen Marshalling.
[Bearbeiten]
Vielleicht sollten Sie versuchen, den Puffer Griff Pinning, und dass an der Struktur Marshalling, anstatt vis kehrt. So etwas wie folgt aus:
DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo;
GCHandle pinnedHandle = GCHandle.Alloc(buffItem, GCHandleType.Pinned);
folderInfo = (DAContentAccessDefinitions.CA_FOLDER_INFO)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(DAContentAccessDefinitions.CA_FOLDER_INFO));
pin.Free();
//folderInfo should contain the data from buffItem
Mit dem festen Schlüsselwort einen Zeiger auf Ihren ursprünglichen folderInfo
zu erhalten.
Es könnte sein, dass nicht verwalteten Ressourcen nicht durch etwas freigesetzt werden. Überprüfen Sie, ob alles, was Sie verwenden implementiert IDisposable und wenn ja, wickeln sie es in einem using { }
Block.