2010-12-07 3 views
1

Ich habe eine COM-Komponente in VB6 geschrieben, die ich von einer Visual Basic .NET-Anwendung über COM-Interop verwende.Warum wirft meine COM-Komponente OutOfMemoryException, aber läuft auf VB6 gut?

Es gibt eine Methode, die beim Aufruf aus VB.NET eine OutOfMemoryException auslöst. Wenn ich genau denselben Aufruf von einer Visual Basic 6-Anwendung ausführe, funktioniert alles jedoch einwandfrei.

Ich kann hier keinen Code schreiben, weil es zu lang und schwer zu folgen ist (ich bin damit beauftragt, es zu reparieren) und ich kann das Problem nicht lokalisieren, weil, wenn ich versuche, es von VB6 zu debuggen, der Fehler nicht t auftauchen.

Was könnte dieses unterschiedliche Verhalten verursachen?

Das funktionierte einwandfrei, bis ich ein Leistungsproblem mit einem Dictionary-Objekt (ein COM von Microsoft Scripting Runtime) behoben. Wenn das Wörterbuch nicht irrational oder undicht wird, sehe ich nicht, wie es das verursachen könnte, da es niemals über 100-200 Elemente hinauswächst und nur eines erstellt wird, bevor die Ausnahme ausgelöst wird.

Ich habe das gleiche Problem mit einem Collection-Objekt und einer peinlichen Exists() -Funktion versucht und das gleiche Problem passiert. Wenn ich früh zurückgehe, indem ich Nothing zurückgebe, funktioniert es (d. H. Es wird NullReferenceException ausgelöst, wie zu erwarten wäre).

+0

Gibt es einen sinnvollen Stacktrace? und was ist mit der Erinnerung? Wie groß ist der Prozess? –

+0

@Simon: Stacktrace endet an der COM/.NET-Grenze. Der Prozess ist etwa 100 MB, wenn die Ausnahme über den Stapel fliegt. –

+0

Das Scripting.Dictionary-COM-Objekt ist als STA (Apartment) gekennzeichnet, wie unten von welootty angegeben. Haben Sie das Threading überprüft? Und BTW, greifen Sie auf dieses Wörterbuch mit mehreren Threads zu? –

Antwort

1

Speicherverwaltung in VB.NET ist sehr unterschiedlich. VB6 verwendet Referenzzählung zum Freigeben von COM-Objekten, VB.NET verwendet den Garbage Collector. Sie können in eine Situation geraten, insbesondere wenn Sie die Komponente testen, wobei der GC nicht häufig genug ausgeführt wird, um die COM-Objekte freizugeben. Diese Objekte weisen nicht verwalteten Speicher zu, der keinen Druck auf den Garbage Collector ausübt, um eine Sammlung zu starten.

Starten Sie die Diagnose mit Perfmon.exe, Systemmonitor. Klicken Sie mit der rechten Maustaste auf das Diagramm, fügen Sie Zähler hinzu und wählen Sie .NET CLR-Speicher, # Gen 0-Sammlungen, und wählen Sie Ihren Prozess aus. Stellen Sie sicher, dass der Zähler mit einer angemessenen Rate von mindestens einer Sekunde inkrementiert wird.

Die Behebung eines solchen Problems ist ziemlich unangenehm. Stellen Sie sicher, dass es sich nicht um ein künstliches Problem handelt, das durch die Isolierung der Komponente verursacht wird. Oder ein einfacher Fehler in Ihrem Code, der einen Verweis auf das COM-Objekt enthält. Durch Aufrufen von GC.Collect() gefolgt von GC.WaitForPendingFinalizers() werden COM-Objekte freigegeben. So ruft Marshal.ReleaseComObject(). Die Verwendung von GC.AddMemoryPressure() ist ebenfalls eine mögliche Problemumgehung, aber Sie müssen eine vernünftige Idee haben, wieviel nicht gemanagter Speicher das COM-Objekt benötigt.

+0

Ein Fehler wegen eines Verweises auf das COM-Objekt ist nicht wahrscheinlich, weil ich den .NET-Teil des Codes nicht berührt habe. Mit perfmon habe ich während einer Ausführung nur sehr wenige Sammlungen gesehen: Es gab nur 10 gen 0 Sammlungen und 2 auf Gen 2 vor dem Werfen. Für den Moment habe ich das Problem behoben, indem ich den Performance-Fix auf die .NET-Layer geschoben habe ... –

Verwandte Themen