2012-12-06 7 views
9

Ich habe gehört, das Kompilieren im Freigabemodus erzeugt optimierten Code als im Debug-Modus, was in Ordnung ist.Wird beim Kompilieren von Release und Debug ein anderer IL-Code und ein anderer Maschinencode generiert?

Aber ist diese Optimierung in der IL? ist es in dem Maschinencode, sobald die CLR es ausführt? unterscheidet sich die Metadatenstruktur von PE, die in Release und Debug kompiliert wurden?

dank

+0

Gute Frage, aber warum möchten Sie wissen? – Cameron

+2

Weil ich in einem Vorstellungsgespräch abgelehnt wurde und sauer wurde. Ich denke, wir Entwickler sollten mehr darüber wissen, wie diese Dinge hinter den Kulissen funktionieren – RollRoll

+0

Große Frage! – nawfal

Antwort

14

Mit Build erstellen in Release wird die Compileroption/optimiert für den C# -Compiler aktiviert. Das hat eine paar Nebenwirkungen, die IL ändert sich aber nicht viel. Bemerkenswert ist, dass der Compiler sich nicht mehr darum bemüht, den Code einwandfrei debuggbar zu machen. Es überspringt beispielsweise einen leeren statischen Konstruktor, es gibt keine NOP-Opcodes mehr aus, mit denen Sie einen Haltepunkt in einer geschweiften Klammer setzen können und lokale Variablen mit unterschiedlichen Bereichen in einem Stapelrahmen überlappen können. Kleines Zeug.

Der wichtigste Unterschied ist das Attribut [Debuggable], das für die Assembly ausgegeben wird. Die IsJITOptimizerDisabled-Eigenschaft ist false.

Welche schaltet den real Optimierer, der in den Jitter eingebaut ist. Sie finden die Liste der Optimierungen in this answer. Beachten Sie die Nützlichkeit dieses Ansatzes, any Sprache Vorteile von Code-Optimierer im Jitter anstelle des Compilers zu haben.

Also kurz gesagt, sehr kleine Änderungen in der IL, sehr große Änderungen im generierten Maschinencode.

+2

tolle Antwort. – RollRoll

3

Ja, es in der IL einige Optimierung ist - insbesondere die Debug-Version wird NOP-Befehle enthalten, die es für einen Debugger leicht machen Bruchstellen einzufügen, glaube ich. Es gibt auch potentielle Unterschiede hinsichtlich der bereitgestellten Debug-Informationen (Zeilennummern usw.).

Ich schlage vor, Sie nehmen ein kleines Beispielprogramm, kompilieren Sie es in beide Richtungen, und dann sehen Sie sich die Ausgabe in ildasm.

Der C# -Compiler nicht tun viel Optimierung - der JIT-Compiler tut das meiste davon - aber ich denke, es gibt einige Unterschiede.

+0

danke, müssten Sie wissen, ob die Metadatenstruktur abhängig vom Kompilierungsmodus geändert wird? – RollRoll

+0

@EdwinSoho: Es ist immer noch das gleiche * Format *. Es hängt wirklich davon ab, was Sie mit "Struktur" meinen. –

1

Die CIL unterscheidet sich, es ist optimiert. Da der Maschinencode eine Übersetzung des CIL ist, unterscheidet er sich auch. Sie können es selbst sehen, öffnen Sie einfach das Demontagefenster im Visual Studio. Metadaten sollten gleich bleiben, da Sie die Struktur von Klassenverträgen zwischen Releases nicht ändern.

0

In VB gibt es einen Nebeneffekt der Edit + Continue-Unterstützung in die ausführbare Datei kompiliert, die einen Speicherverlust verursachen kann. Es wird von jedem Ereignis betroffen, das mit dem WithEvents-Schlüsselwort deklariert wird. Eine WeakReference verfolgt diese Ereignisinstanzen. Problem ist, dass diese WeakReferences durchgesickert sind, wenn Sie die App ohne einen Debugger ausführen. Die Rate, mit der der Prozess Speicher verbraucht, hängt stark davon ab, wie viele Instanzen der Klasse erstellt werden. Das Leck beträgt 16 Byte pro Ereignis pro Objekt.

Haftungsausschluss: kopiert von Hans' Antwort here

this Microsoft knowledge base article See.

0

Dies ist keine Antwort auf die genaue Frage.Nur um hinzuzufügen, dass Sie absichtlich markieren können, welcher Code im Debug-Modus und im Freigabemodus mit Hilfe von Präprozessor Markups ausgeführt werden muss.

#if DEBUG 
    // code only meant for debug mode 
#endif 

#if NOT DEBUG 
    // code only meant for release mode 
#endif 

Also, wenn Sie dies tun, würden Sie verschiedene IL generieren.