# Unterschied zwischen "Debug" und "Run"



## JFreak (13. Dez 2008)

Hallo,

ich implementiere gerade ein kleines Programm in Eclipse und habe Ewigkeiten im Debugger nach einem Fehler gesucht. Nun ist mir aufgefallen, dass es gar kein Fehler war, sondern das sich das Programm im Debug-Modus (F11) und im Run-Modus (Ctrl-F11) anders verhält. Wenn mich nicht alles täuscht, ist Java doch sowohl determiniert als auch deterministisch... Was ist da los?

Ich arbeite hauptsächlich mit Set<String>. Meine Hauptdatenstruktur ist Set<Set<String>,Set<String>>. Schon beim Initialisieren treten Unterschiede auf:

```
[d, c]->[f, e, b]
[e]->[b, c, a]
[f]->[d, c]
[c]->[d, a]
[a]->[b, c]
```
(run)

```
[f]->[d, c]
[d, c]->[f, e, b]
[a]->[b, c]
[e]->[b, c, a]
[c]->[d, a]
```
(debug)

Ich verändere nichts an der Ausgangssituation... Das ist sehr, sehr seltsam.

Grüße,

Lars


----------



## Wildcard (13. Dez 2008)

Ich habe zwar keine Ahnung was du uns mit diesen Code Blöcken sagen willst, aber vermutlich ist deine Run Configuration eine andere als deine Debug Configuration


----------



## JFreak (13. Dez 2008)

Ich initialisiere meine Datenstruktur mit diesen Werten und habe sie testweise gleich ausgeben lassen. Offensichtlich gibt es da Unterschiede, wie das HashSet die Strings sortiert.
Run- und Debug-Configuration habe ich unangetastet gelassen, aber nach drüberschauen kann ich keinen Unterschied feststellen. Welcher Schalter könnte das sein? Bei Compiler- und VM-Argumenten gibt es jedenfalls keinen, die sind überall leer.


----------



## maki (13. Dez 2008)

>> Set<Set<String>,Set<String>>

Wassol denn das sein?
Sowas gibt's doch gar nicht in Java, zumindest nicht mit Set, oder meintest du Map?


----------



## Wildcard (13. Dez 2008)

Vielleicht startest du auch nichtmal die gleiche Klasse. Es wird entweder anhand deiner aktuellen Selektion versucht die passende Configuration zu ermittlen, oder (je nach Einstellung) die zuletzt gestartete.


----------



## JFreak (13. Dez 2008)

Habe mich vertippt... Es ist so etwas wie Map, genauer gesagt Set<FD>, wobei FD eine nicht-statische innere Klasse ist, die als Attribute zwei Set<String>s hat.

[EDIT2] Link zum fehlerhaften Code entfernt.


----------



## Wildcard (13. Dez 2008)

Dich stört die Reihenfolge? hashCode sagt folgendes:


> Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.


Da steht nicht das es bei 2 Programmstarts den selben Wert liefert.


----------



## JFreak (13. Dez 2008)

Hmpf. So ein Zufall kommt ja selten... Beim "Run" hat die Reihenfolge der einzelnen Objekte einen Bug überdeckt, der nur beim "Debug" zum Vorschein kommt. Die Idee mit dem hashCode hat mich drauf gebracht.

[gelöst]


----------



## maki (13. Dez 2008)

> Beim "Run" hat die Reihenfolge der einzelnen Objekte einen Bug überdeckt, der nur beim "Debug" zum Vorschein kommt.


Welcher Bug war denn das?
Und wieso kommt der nur bei Debug vor?

Persönlich bin ihc kein Fan von Debuggern, eher als Notlösung.
Unittests & Logging bringen imho mehr.


----------



## JFreak (13. Dez 2008)

Das ist die Berechnung der kanonischen Überdeckung einer Menge von funktionalen Abhängigkeiten bei einer Relation. Grob gesagt ist eine funktionale Abhängigkeit (FD) eine Abbildung von einer Menge von Spalten einer Tabelle auf eine andere Menge. Für diese Abbildungen gelten nun Transitivität etc.
Für eine Menge von FDs möchte man nun erreichen, dass diese minimal ist. Also entfernt man Elemente aus der Abbildung und sieht nach, ob alles noch funktioniert, d. h. ob keine Information verlorengeht. Der Algorithmus entfernt schrittweise. Weil ich aber während des Iterierens über ein Set keine strukturellen Veränderungen machen darf, habe ich ein zweites Set, welches sich die Änderungen "merkt" und am Ende der Berechnung zurückschreibt. Dummerweise hatte ich vergessen, die Änderungen nach jedem Schritt rückgängig zu machen, damit immer dieselben Ausgangsbedingungen herrschen. Es war also ein Zufall, dass es bei "Run" geklappt hat. Tatsächlich scheinte der Debugger andere Speicherbereiche zu verwenden als im "Run"-Modus, daher hat sich der Hashcode geändert, dadurch wiederum die Reihenfolge im Set, dadurch die Abarbeitungsreihenfolge im Algorithmus...

Im Entstehen eines Programmes bin ich doch recht froh, dass Java für solch mächtige Debugging-Features ausgelegt ist. Unittest bringen eher zur Fehlerentdeckung etwas als zur Fehlersuche. Logging finde ich persönlich für solche Zwecke unhandlich, aber für eine echte Aussage darüber habe ich noch zu wenig damit gearbeitet.

[EDIT] vgl: http://paste.frubar.net/9551 (neu) und http://paste.frubar.net/9550 (alt)


----------



## maki (14. Dez 2008)

> Unittest bringen eher zur Fehlerentdeckung etwas als zur Fehlersuche.


Das wüde ich nicht unterschreiben, widerspricht meiner Erfahrung.

Trotzdem ist es schräg & verunsichernd das Programme im Debug Mode anders laufen als im "Normalmodus", noch nein Grund von Debugging abstand zu halten imho.


----------



## Zed (14. Dez 2008)

Ich nehme mal an dein Set war ein HashSet und deine Map war eine HashMap. Die beiden garantieren keine feste Reihenfolge. LinkedHashSet und LinkedHashMap dagagen schon.

Und zum Thema Hashcode der ist immer gleich ausser das Programm wurde neu gestartet.


----------



## maki (14. Dez 2008)

Seltsamerweise hat das Programm immer identische Werte & Reichenfolgen produziert, der Unterschied war einzig und allein zwischen Run und Debug.


----------



## Wildcard (14. Dez 2008)

maki hat gesagt.:
			
		

> Seltsamerweise hat das Programm immer identische Werte & Reichenfolgen produziert, der Unterschied war einzig und allein zwischen Run und Debug.


Der Default Hashcode verwendet Speicheradressen. Durchaus möglich das beim Eclipse Debug andere Speicheradressen verwendet werden um das hot swapping zu ermöglichen.
Ist doch aber auch völlig egal ob Run immer die gleichen Werte produziert, wenn etwas als unsortiert deklariert ist, sollte man keinerlei Annahmen über die Reihenfolge treffen.


----------



## maki (14. Dez 2008)

Ja, auch wieder richtig


----------



## JFreak (14. Dez 2008)

Eben das war ja das Problem, es war ein Bug, der in einer gewissen Reihenfolge (nämlich die bei Run) nicht aufgetreten ist. Wenn Unittest so wärmstens empfohlen werden, dann sehe ich die mir mal genauer an.


----------



## maki (14. Dez 2008)

Speziell testgetribenes Vorgehen (Test Driven Development) hat viele Vorteile.


----------

