GC-Verhalten inkonsistent zwischen 32-Bit- und 64-Bit-Anwendungen

9

Ich habe inkonsistentes Verhalten vom GC festgestellt, als ich Konsolenanwendungen unter 32-Bit und 64-Bit in .Net 4.0 mit VS 2013 kompiliert habe.

Betrachten Sie den folgenden Code:

%Vor%

und in Main() ...

%Vor%

Bei Ausführung im 64-Bit-Modus (Debugmodus) funktioniert jedes Mal ohne Fehler; Im 32-Bit-Modus kann ich jedoch nicht zwingen, dass dieses Objekt gesammelt wird (selbst wenn ich mehr Objekte erstelle und eine bestimmte Zeit abwarte, die ich ausprobiert habe).

Hat jemand irgendwelche Ideen, warum das so ist? Es verursacht mir Probleme, wenn ich versuche, Code zu debuggen, der sich mit der Freigabe nicht verwalteter Proxy-Daten für die 32-Bit-Version der Assemblys befassen muss. Es gibt viele Objekte im 32-Bit-Modus, die nur lange Zeit dort verweilen (nicht so in 64-Bit).

Ich versuche etwas im 32-Bit-Modus zu debuggen, aber die Finalizer werden nicht aufgerufen (zumindest nicht mit Gewalt). Die Objekte sitzen einfach da und werden nie gesammelt (ich kann alle schwachen Referenzen sehen, die immer noch einen Wert haben). Im 64-Bit-Modus werden alle schwachen Referenzen wie erwartet gelöscht und alle Finalizer werden aufgerufen.

Hinweis: Obwohl der obige Code sehr klein ist, habe ich im 32-Bit-Modus festgestellt, dass viele mehr Objekte im GC hängen bleiben, bis später weitere Objekte erstellt werden (auch wenn "Collect"). und "WaitForPendingFinalizers" wird aufgerufen). Dies ist im 64-Bit-Modus niemals der Fall. Ich habe einen Benutzer gefragt, warum so viele Objekte nicht gesammelt werden, was mich untersuchen ließ, zu dem ich herausfand, dass im 64-Bit-Modus alles besser funktioniert als 32. Ich versuche nur zu verstehen, warum.

Bearbeiten: Hier ist besser Code, um die Unterschiede zu zeigen:

%Vor%

Es funktioniert in 64-Bit, aber nicht in 32-Bit. Auf meinem System wird "Test # 9" niemals gesammelt (eine schwache Referenz bleibt bestehen), selbst nach dem Erstellen weiterer Objekte, und ein zweites Mal versuchen.

Zu Ihrer Information: Der Hauptgrund für die Frage ist, dass ich eine \gctest -Option in meiner Konsole habe, um die Garbage Collection zwischen V8.Net und der zugrunde liegenden V8-Engine auf der nativen Seite zu testen. Es funktioniert in 64-Bit, aber nicht in 32.

    
James Wilkins 15.05.2015, 08:05
quelle

1 Antwort

3

Keine Repro auf VS2013 + .NET 4.5 auf x86 und x64:

%Vor%

Beachten Sie, dass (wie von @Sriram Sakthivel bemerkt) "Geister" -Kopien Ihrer Variablen vorhanden sein können, deren Lebensdauer bis zum Ende der Methode verlängert wurde (wenn Sie den Code im Debug-Modus kompilieren oder eine Debugger angehängt (F5 statt Strg + F5), wird die Lebensdauer Ihrer Variablen bis zum Ende der Methode verlängert, um das Debuggen zu erleichtern)

Zum Beispiel Objektinitialisierung (wenn Sie etwas wie neu tun Foo {I = 5}) erstellt eine versteckte lokale Variable.

    
xanatos 15.05.2015 08:47
quelle