Das Initialisieren eines großen gezackten Arrays beansprucht 1 GB RAM und stürzt mit StackOverflowException ab

8

Wenn ich dieses Stück C # -Code (Volltext) kompiliere und das ArrayTest.exe , der Prozess hängt für ein paar Sekunden, verbraucht 1 GB RAM und stürzt mit StackOverflowException ab. Warum?

%Vor%

Ich verwende Microsoft Visual C # Compiler Version 4.0.30319.33440 für Microsoft (R) .NET Framework 4.5. Ich rufe nur csc.exe in der Befehlszeile auf und führe die kompilierte EXE aus. Das Problem verschwindet, wenn ich das csc /optimize Flag hinzufüge. Das obige Snippet ist in der Tat der gesamte Code, mit dem ich gerade teste - es gibt keine nützliche Arbeit in Main (), nachdem das Array initialisiert wurde.

Problemkontext: Ich habe versucht, eine Menge numerischer Testfälle in ein Programm zu schreiben. In Java, JavaScript oder Python würde der Code unschuldig aussehen und ordnungsgemäß funktionieren:

%Vor%

Aber als ich in C # versucht habe, einen solchen Code zu kompilieren, hat die Array-Initialisierung eine beachtliche Zeit (~ 5 Sekunden) gekostet, sogar bevor die For-Schleife mit dem test() starten konnte.

Mein tatsächlicher Code wurde auf die obige MVCE reduziert, wobei struct Point keine Felder enthält und Main() nur die Array-Initialisierung und keine nützliche Arbeit enthält.

    
Nayuki 19.09.2016, 22:27
quelle

1 Antwort

7

Okay, ich habe mit der Kompilierung der Debug / Release-Versionen Ihrer Klassendatei begonnen. Mit dem VS 2015-Compiler in der Version 14.0 der Tools ist die Ausgabe für die IL identisch. Dies deckt den Grund, warum Leute Probleme nicht bemerkt haben.

Debug vs Release im vorherigen Compiler in VS 2013 ist ziemlich sofort verdammt. Ausgabe der ausführbaren Datei im Debug-Modus ist 2,091 kb. IL von der Release-Version zeigt an, dass es das tatsächliche Objekt ignoriert, da es nie verwendet wird. Okay gut. Ich werde VS 2015 Debug IL mit dem VS 2013 Debug IL vergleichen.

Ich habe die Array-Größe der Kürze halber auf 3x3 geändert.

Hier ist die Ausgabe der IL 2015:

%Vor%

Der Hauptunterschied zwischen diesem Code und dem Freigabemodus besteht in der zusätzlichen nop-Anweisung.

Hier ist die Ausgabe für die Version 2012/2013 des Compilers:

%Vor%

Also, in dem 2012/2013 Compiler, den Sie verwenden, macht der Debug-Modus eine sehr große Anzahl von Stack-Zuweisungen, wahrscheinlich, damit Sie die gesamte gezackte Array-Struktur während der Bearbeitung intelliSense und weitermachen können, oder möglicherweise so Schritt in jede einzelne Objektkonstruktion. Da bin ich mir überhaupt nicht sicher.

Ich bin kein Experte für IL, aber es scheint mir, dass es für jeden Punkt zuweist, dann wieder für jedes Array, dann wieder für das gezackte Array, was zu viel Zuweisungen führt.

    
Jonathon Chase 20.09.2016 00:53
quelle

Tags und Links