Forum: PC-Programmierung Programmabsturz eines Consolenprogramms unter Windows - wie Fehler finden?


von Gerhard Z. (germel)


Angehängte Dateien:

Lesenswert?

Hallo Forengemeinde,

habe ein Kommandozeilen-Programm unter Linux in C entwickelt und danach 
auch mit MingW für Windows kompilieren können. Das Programm liest eine 
Audio Datei im Waveformat und eine Textdatei ein und "filtert" mit 
Kommandos aus der Textdatei die Audiodatei in 3 neue Dateien im 
Waveformat.

Unter Linux kompiliere ich mit gcc 4.7.3 bzw. cross-kompiliere für 
Windows mit dem i686-w64-mingw32-gcc 4.6.3. Das Programm läuft 
anstandslos unter Linux und in der VirtualBox unter Windows 7. Es stürzt 
ab auf mehreren anderen Windows 7 Computern mit einem lapidaten Popup 
(siehe Anhang). Dies passiert auch, wenn ich das Programm direkt unter 
Windows 7 mit MingW compiliere.

Jetzt zu meiner Frage: Wie kann ich am besten unter Windows den Fehler 
einkreisen. Habe auf den Windows7 Computern keine Administrationsrechte 
und damit auch keine Entwicklungsumgebung. Die Entwicklungsumgebung habe 
ich in der virtuellen Windos-Installation. Dort stürzt das Programm aber 
nicht ab.

Habe verzweifelt printf Aufrufe in den Programmfluss eingestreut und 
vermeintlich die Absturzstelle eingekreist. Kommentiere ich sie aber aus 
stürzt das Programm zu beliebig späterer Zeit ab. Habe mit Debugoptionen 
(-g) und ohne Optimierung (-O0) übersetzt aber ich bekomme einfach keine 
Fehlermeldung auf die Konsole.

Habt ihr eine Idee, wie ich das Programm (oder Windows) dazu zwingen 
kann, mir mehr Informationen über den Grund des Absturzes zu sagen? 
Übrigens hat das Fehler-PopUp einen Hinweis "Windows can check online 
for a solution ...". Wenn man den anwählt kreist eine Weile die Sanduhr, 
dann geht das Fenster ohne weitere Meldung zu - danke Microsoft!

Jede Hilfe ist willkommen.

Gerhard

von Jens G. (jensig)


Lesenswert?

Mit adplus den CallStack rausschreiben lassen, bei dem es crasht. Ist, 
wenn ich mich richtig erinnere, Teil irgendeines Win SDKs. Ob das aber 
admin Rechte braucht, weis ich nicht.

von Karl H. (kbuchegg)


Lesenswert?

Klingt nach irgendeinem Stack Überschreiber. DIe zeigen gerne mal solche 
Symptome.
Also: alle Array Zugriffe checken. Die sind die häufigste Ursache für 
solche Dinge.

Wenn das Programm nicht allzugross ist und vor allen Dingen nicht noch 
von zig anderen Libraries abhängt, kannst du ja mal den Source Code 
posten.

von Dirk B. (dirkb2)


Lesenswert?

Karl Heinz schrieb:
> Klingt nach irgendeinem Stack Überschreiber.
Evtl. ist auch der Stack zu klein.

von Peter II (Gast)


Lesenswert?

einfach mal mit dem gdb unter Windows starten?

von Gerhard Z. (germel)


Lesenswert?

Dirk B. schrieb:
> Karl Heinz schrieb:
>> Klingt nach irgendeinem Stack Überschreiber.
> Evtl. ist auch der Stack zu klein.

habt ihr parat, wie ich dem gcc mitteile, dass er den Stack vergrößern 
soll?

Ja, und den gdb.exe als ausführbares Programm (ohne Installation) hab 
ich inzwischen gefunden. Versuche gerade, das Programm darin zum Laufen 
zu bringen. Hab halt leider bisher selten direkt in ihm arbeiten müssen 
sondern hab den ddd benutzt.

Danke schon mal
Gerhard

von Peter II (Gast)


Lesenswert?

Gerhard Z. schrieb:
> habt ihr parat, wie ich dem gcc mitteile, dass er den Stack vergrößern
> soll?

das sollte keine Option vom Compiler sein. Beim starten eine threads 
kann man die Stackgröße mitgeben. Aber wie es beim Hauptprogramm geht 
kann ich nicht sagen.

Aber ich halte es für unwahrscheinlich das das Problem dort liegt, dann 
müsste das verhalten immer Konstant sein.

von Gerhard Z. (germel)


Lesenswert?

Jetzt wird's ganz verrückt. Habe das Programm im Debugger laufen lassen. 
Mit Parametersatz1 in der Textdatei läuft es durch ohne Fehler und 
erzeugt alle Dateien ordentlich.

Mit Parametersatz 2 läuft es bis zum Ende durch (die letzten beiden 
Befehle in der main sind ein printf und return 0;), das latzte printf 
wird gemacht und die Dateien sind geschrieben aber es beendet mit 
Fehlermeldung

[Thread 8812.0x1914 exited with code 0]

Program received signal SIGSEGV, Segmentation fault.
0x77bbfdaa in ntdll!RtlUnwind () from C:\Windows\SYSTEM32\ntdll.dll

Wenn ich beide Aufrufe direkt von der Kommandozeile aufrufe kommt der 
ganz oben beschriebene Fehler beide male, die Dateien sind alle 
angelegt, aber ohne Inhalt.

Im Debugger bekomme ich also Ergebnisse, außerhalb nicht. Ich weiß nicht 
mehr weiter.

Noch irgend eine Idee?
Gerhard

von Peter II (Gast)


Lesenswert?

Gerhard Z. schrieb:
> Noch irgend eine Idee?

hast du mehre Threads?

Willst du uns den quellcode mal zeigen?

von Gerhard Z. (germel)


Lesenswert?

nein, habe nur einen Thread (ich habe jedenfalls nichts explizit 
angelegt und die Programmabfolge ist linear).

Das eigentliche Programm läuft auf einer ARM Hardware im Controlling 
Bereich und ich habe jetzt zusätzlich ein Rahmenprogramm drumherum 
geschrieben, welches die IOs der Hardware emuliert. Man kann jetzt also 
den Programmablauf am PC simulieren (mit den Wavedateien als 
Eingangsdaten). Das klappt ja auch unter Linux und unter Windows in 
meiner virtuellen Box sehr gut, leider nicht auf richtiger 
Windowshardware.

Ich würde das Programm gerne zeigen (obwohl es aus relativ vielen 
Modulen besteh), habe aber ein Confidential Agreement unterschreiben 
müssen und darf daher nichts rausrücken.

Sorry
Gerhard

von Peter II (Gast)


Lesenswert?

Gerhard Z. schrieb:
> nein, habe nur einen Thread (ich habe jedenfalls nichts explizit
> angelegt und die Programmabfolge ist linear).

merkwürdig, damit sollte das Programm eigentlich immer das gleiche 
Verhalten zeigen.
Sind alle Eingangsgrößen wirklich immer gleich oder gibt dinge die jedes 
mal anders sind?

Unter Windows gibt es den dr.Watson, damit lässt sich ein dump 
wegschreiben, wenn das Pogramm ein Fehler hat. Diese kann man dann 
analysieren.

Man kann sogar einen eignen Crash-handler schreibem und dann einen 
minidump vom ram erzeugen, das auswerten ist dann aber immer recht 
mühselig.

http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplus
https://msdn.microsoft.com/de-de/library/windows/desktop/ms680360(v=vs.85).aspx

von Peter II (Gast)


Lesenswert?

Nachtrag:

hast du die Möglichkeit das Programm mit dem Visual-Studio zu bauen? 
Denn dort gib es kann auch eine remotedebugger. Den muss man nicht auf 
den fremden System installieren.

Dann könntest du von einen Anderen PC mit dem VS remote auf den 
Problem-Computer Debugger.

von Karl H. (kbuchegg)


Lesenswert?

Gerhard Z. schrieb:
> Jetzt wird's ganz verrückt. Habe das Programm im Debugger laufen lassen.
> Mit Parametersatz1 in der Textdatei läuft es durch ohne Fehler und
> erzeugt alle Dateien ordentlich.

Hmm.
Mit dem Microsoft Compiler wäre sowas unter anderem ein starkes Indiz 
für die Verwendung einer nicht initialisierte Variablen. Könnte 
allerdings immer noch ein Array Overflow sein.

> Im Debugger bekomme ich also Ergebnisse, außerhalb nicht. Ich weiß nicht
> mehr weiter.

Abspecken. Zerlegen in Einzelmodule und einzeln rigoros testen.

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Windows kann auch einen Crashdump erzeugen, der findet sich unter
c:\programdata\microsoft\windows\werfault\reportqueue\

Für jeden Absturz gibt es hier wiederum ein nach dem Prozess und 
diversen anderen Dingen benanntes Verzeichnis, in dem der jeweilige 
Crashdump zu finden ist.

Diesen Crashdump wiederum kann der Debugger des Visual Studio 
verarbeiten, das sollte aber auch der Windbeutel (Windbg) hinbekommen.

Ob es einen Weg gibt, so etwas mit gdb auszuwerten, muss man die 
gcc/gdb-unter-Windows-Fraktion fragen.

Früher* wurde ein Crashdump in Textform von drwtsn32 erzeugt, der 
enthielt neben einem einfachen Stackdump auch ein Disassemblat der 
Stelle des Absturzes.

Die "neuzeitlichen" Crashdumps sind zum Debuggen aber deutlich besser 
geeignet, weil man sich mit ihnen auch lokale/globale Variablen, 
Speicherinhalte etc. betrachten kann, ohne gleich auf der Assemblerebene 
hantieren zu müssen -- sofern der verwendete Debugger das unterstützt.


*) bis einschließlich Windows XP / 2003

von Gerhard Z. (germel)


Lesenswert?

Karl Heinz schrieb:
> Abspecken. Zerlegen in Einzelmodule und einzeln rigoros testen.

Ja, ich glaube, da muss ich durch. Habe an mehreren Stellen malloc im 
Program um Platz zu scghaffen, um Binärdateien 1:1 in den Speicher 
einzulesen. Habe jetzt mal einfach den doppelten Platz reserviert. 
Programm stürzt zwar auch ab, aber jetzt sind die Ergebnisse 
geschrieben. Wenn ich aber z.B. den 4-fachen Platz reserviere, dann 
stürzt es wieder ab und alle Dateien haben 0 Byte.

Es wird schon was in die Richtung Array Überschreiben sein. Ich bin halt 
kein Windows Entwickler und habe auf den Kisten keine Admin Rechte. 
Alles in Richtung Visual Studio oder ähnliches ist lieb gemeint, hilt 
mir aber im Moment nichts. Müsste erst ein eigenes Windows System 
aufsetzen und entsprechende Toolchains installieren. Da scheu ich ein 
bisschen vor zurück.

Blöd, dass sich der Fehler weder unter Linux noch im VirtualBox Windows 
zeigt.

Hör für heute erst mal auf, vielen Dank erst mal für die vielen 
Vorschläge.
Gerhard

von Karl Käfer (Gast)


Lesenswert?

Hallo Gerhard,

Gerhard Z. schrieb:
> Ja, ich glaube, da muss ich durch. Habe an mehreren Stellen malloc im
> Program um Platz zu scghaffen, um Binärdateien 1:1 in den Speicher
> einzulesen. Habe jetzt mal einfach den doppelten Platz reserviert.
> Programm stürzt zwar auch ab, aber jetzt sind die Ergebnisse
> geschrieben. Wenn ich aber z.B. den 4-fachen Platz reserviere, dann
> stürzt es wieder ab und alle Dateien haben 0 Byte.

Ohne Sourcecode kann man natürlich nicht viel sagen, aber vielleicht hat 
das Verhalten Deines Programms auch etwas mit unterschiedlichen 
Zeichensätzen zu tun. Linux nutzt meist UTF-8, Windows IMHO jedoch 
UTF-16.

HTH,
Karl

von Konrad S. (maybee)


Lesenswert?

Mit diesen Tools kann man einiges an Speicher-Bugs aufdecken:
http://duma.sourceforge.net/
http://valgrind.org/ und http://valgrind.org/downloads/guis.html

Von Unix/Linux her kommend bietet Windows dem Programmierer ein paar 
Fallstricke, mit denen der überhaupt nicht rechnet. Z.B. FILE-Pointer, 
allozierte Speicherbereiche oder ähnliche "Handles", die man aus 
irgendwelchen Libraries bekommt, im eigenen Code schließen/freigeben ... 
und dann PENG

von Christian R. (supachris)


Lesenswert?

Hat denn jedes Mallc sein free? Und ist eventuell in der VM 32 Bit und 
in dem echten System 64 Bit? Dann ist vielleicht irgendwo nicht bedacht 
dass ein Pointer dann 8 Byte groß ist...

von Rolf M. (rmagnus)


Lesenswert?

Der Fehler wird vermutlich auch in der Linux-Version enthalten sein und 
sich dort nur nicht mit einem Absturz auswirken. Du könntest diese mal 
in valgrind laufen lassen. Das zeigt dir recht ausführlich an, wenn du 
irgendwo Unfug mit Speicher treibst. Vor allem kann es dabei auch auf 
die Zeile verweisen, wo der Ursprung des Fehlers liegt, statt wie bei 
einem klassischen Debugger nur auf die, wo er sich auswirkt.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

Gerhard Z. schrieb:
> Mit Parametersatz 2 läuft es bis zum Ende durch (die letzten beiden
> Befehle in der main sind ein printf und return 0;), das latzte printf
> wird gemacht und die Dateien sind geschrieben aber es beendet mit
> Fehlermeldung
>
> [Thread 8812.0x1914 exited with code 0]
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x77bbfdaa in ntdll!RtlUnwind () from C:\Windows\SYSTEM32\ntdll.dll

Dann wird wohl in der ntdll nach Programmende etwas erneut freigegeben.

> Wenn ich beide Aufrufe direkt von der Kommandozeile aufrufe kommt der
> ganz oben beschriebene Fehler beide male

Ja, dass kenn ich. Valgrind hilft mir bei solchen Problemen immer.

> die Dateien sind alle
> angelegt, aber ohne Inhalt.

Suche im current working directory, dem Programmverzeichnis, dem 
Zielverzeichnis und den Dokumenten nach Dateien mit kryptischen namen, 
sind möglicherweise versteckt. In diesen temporären Dateien könnte sich 
der fehlende inhalt befinden.

PS: Wie öffnest und schliest du die Dateien (funktionsname)

von Peter II (Gast)


Lesenswert?

Gerhard Z. schrieb:
> Ich bin halt
> kein Windows Entwickler und habe auf den Kisten keine Admin Rechte.
> Alles in Richtung Visual Studio oder ähnliches ist lieb gemeint, hilt
> mir aber im Moment nichts. Müsste erst ein eigenes Windows System
> aufsetzen und entsprechende Toolchains installieren. Da scheu ich ein
> bisschen vor zurück.

und warum? Wenn man für Windows Programm entwickelt sollte man zumindest 
auch eine passende Umgebung für die Fehlersuche haben.

In einer VM einfach mal das Setup zu starten kann ja wohl nicht so 
schwer sein. Vermutlich ist das Problem mehr das Projekt mit dem VS zu 
übersetzen. Aber man hat den Vorteil das ein andere Compiler eventuell 
das Problem anders darstellt und man so auf die Lösung kommt.

von Gerhard Z. (germel)


Lesenswert?

Rolf Magnus schrieb:
> Der Fehler wird vermutlich auch in der Linux-Version enthalten sein

ja, nehme ich auch an, von daher ist valgrind ein guter Tip. Hab ich 
noch nie benutzt, aber irgendwann ist immer das erste Mal.

> Hat denn jedes Mallc sein free?
Nein, es gibt kein free; der Speicher wird bis zum Programmende benutzt 
und ich bin davon ausgegangen, dass das Betriebssystem beim Terminieren 
des Programms den Speicher freigibt. Ist da mein Denkfehler?

> Wie öffnest und schliest du die Dateien?
fp = fopen(FileName, "rt");
fclose(fp);

Danke für die rege Beteiligung
Gerhard

von Gerhard Z. (germel)


Lesenswert?

Gerhard Z. schrieb:
>> Wie öffnest und schliest du die Dateien?
> fp = fopen(FileName, "rt");
> fclose(fp);

bzw.
fp = fopen(FileName, "rb");
für die Dateien im wav-Format

Gerhard

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Karl Käfer schrieb:
> aber vielleicht hat das Verhalten Deines Programms auch etwas mit
> unterschiedlichen Zeichensätzen zu tun. Linux nutzt meist UTF-8, Windows
> IMHO jedoch UTF-16.

Was da verwendet wird, hängt von den Compilereinstellungen und. 
verwendeten Laufzeitbibliotheken ab; es können sowohl Unicode als auch 
MBCS verwendet werden (MBCS fasst UTF-8 und das Verwenden von 
8-Bit-Codepages zusammen, für Konsolapplikationen ist CP850 bzw. CP437 
üblich).

Christian R. schrieb:
> Und ist eventuell in der VM 32 Bit und in dem echten System 64 Bit? Dann
> ist vielleicht irgendwo nicht bedacht dass ein Pointer dann 8 Byte groß
> ist...

Das entscheidet der Compiler. Ein 32-Bit-Programm ist ein 
32-Bit-Programm, auch wenn es unter einem 64-Bit-OS ausgeführt wird. 
Sofern also das gleiche Binary in der VM und in der "Testumgebung" 
verwendet wird, kann das nicht die Ursache sein.

Wenn das Programm hingegen mit unterschiedlichen Compilern übersetzt 
wird, gibt es viele interessante Möglichkeiten.


Gerhard Z. schrieb:
> Nein, es gibt kein free; der Speicher wird bis zum Programmende benutzt
> und ich bin davon ausgegangen, dass das Betriebssystem beim Terminieren
> des Programms den Speicher freigibt. Ist da mein Denkfehler?

Nein, einen Crash in ntdll ergibt so ein Speicherleck nicht.
Das gibt maximal diverse Ausgaben auf der Debugkonsole, was aber nur 
geschieht, wenn man einen Compiler mit entsprechender 
Debug-Laufzeitumgebung und diversen Speichertests zur Laufzeit 
verwendet.

Ohne aktiver Debugkonsole sieht man davon nichts.

: Bearbeitet durch User
von Rolf Magnus (Gast)


Lesenswert?

Peter II schrieb:
> Wenn man für Windows Programm entwickelt sollte man zumindest
> auch eine passende Umgebung für die Fehlersuche haben.
>
> In einer VM einfach mal das Setup zu starten kann ja wohl nicht so
> schwer sein.

Man sollte schon alles lesen:

Gerhard Z. schrieb:
> Die Entwicklungsumgebung habe ich in der virtuellen Windos-Installation.
> Dort stürzt das Programm aber nicht ab.

von Karl H. (kbuchegg)


Lesenswert?

Gerhard Z. schrieb:
> Karl Heinz schrieb:
>> Abspecken. Zerlegen in Einzelmodule und einzeln rigoros testen.
>
> Ja, ich glaube, da muss ich durch. Habe an mehreren Stellen malloc im
> Program um Platz zu scghaffen, um Binärdateien 1:1 in den Speicher
> einzulesen. Habe jetzt mal einfach den doppelten Platz reserviert.
> Programm stürzt zwar auch ab, aber jetzt sind die Ergebnisse
> geschrieben. Wenn ich aber z.B. den 4-fachen Platz reserviere, dann
> stürzt es wieder ab und alle Dateien haben 0 Byte.

Ja.
Aber blindes Rumprobieren hilft hier nicht weiter.

> Alles in Richtung Visual Studio oder ähnliches ist lieb gemeint, hilt
> mir aber im Moment nichts. Müsste erst ein eigenes Windows System
> aufsetzen und entsprechende Toolchains installieren. Da scheu ich ein
> bisschen vor zurück.

Ist eine Sache auf 10 Minuten, in denen die Kiste ganz alleine werkelt. 
Man kann MS viel vorwerfen, aber die Installation vom Dev-Studio läuft 
problemlos durch. Am Anfang die 'üblichen Verdächtigen' einstellen und 
der Rest geht von alleine.

von Karl H. (kbuchegg)


Lesenswert?

Peter II schrieb:

> Aber man hat den Vorteil das ein andere Compiler eventuell
> das Problem anders darstellt und man so auf die Lösung kommt.

Das ist sowieso immer gut.
Jeder Compiler wirft andere Warnungen. Je mehr Compiler drüber gejagt 
werden, desto mehr dubiose Stellen findet man meistens.

von Karl H. (kbuchegg)


Lesenswert?

valgrind ist gut.

Die MS-Runtime kann auch weiterhelfen.
Die Debug Build Versionen von malloc und free machen zusätzlichen 
Speichercheck.
https://msdn.microsoft.com/en-us/library/2f7sy2e9.aspx?f=255&MSPPError=-2147217396
Technisch ist das so gelöst, dass malloc etwas mehr Speicher reserviert 
als angefordert und in diesen Überschussspeicher ein bestimmtes Muster 
reinschreibt. Bei einem free (bzw beim Aufruf von bestimmten Funktionen) 
werden diese Speicherbereiche abgesucht, ob das Muster immer noch 
drinnen steht. Wenn nicht, dann hat in der Zwischenzeit irgendein Code 
den Speicher überschrieben, obwohl er nicht sollte.

von Karl H. (kbuchegg)


Lesenswert?

utf8 versus utf16 glaub ich nicht.

Das Projekt besteht darin eine WAV Datei einzulesen, durch Filter zu 
jagen und die gefilterten Ergebnisse auf neue Dateien auszugeben.
Da ist nicht viel String Verarbeitung im Spiel.
Ich schätze mal, dass irgendeiner der Filter schlampig gemacht ist, und 
seine Ausgabespeicherfläche überläuft. Aber das ist nur eine erste 
Schätzung basierend auf den üblichen und häufigen Fehlermustern.

Blöd ist natürlich, dass der TO keinen Code zeigen kann. So umfangreich, 
denke ich mal, kann diese Aufgabenstellung nicht sein, dass man da nicht 
mit formalen Kriterien einfach mal den Code durchackert und an allen 
dubiosen Stellen mal ein paar assert reinwirft.

von Udo S. (urschmitt)


Lesenswert?

Karl Heinz schrieb:
> Technisch ist das so gelöst, dass malloc etwas mehr Speicher reserviert
> als angefordert und in diesen Überschussspeicher ein bestimmtes Muster
> reinschreibt. Bei einem free (bzw beim Aufruf von bestimmten Funktionen)
> werden diese Speicherbereiche abgesucht, ob das Muster immer noch
> drinnen steht. Wenn nicht, dann hat in der Zwischenzeit irgendein Code
> den Speicher überschrieben, obwohl er nicht sollte.

Das ist schön und gut, aber der TO gibt seinen Speicher ja nicht frei 
weil das das Betriebssystem für ihn tut:

Gerhard Z. schrieb:
>> Hat denn jedes Mallc sein free?
> Nein, es gibt kein free; der Speicher wird bis zum Programmende benutzt
> und ich bin davon ausgegangen, dass das Betriebssystem beim Terminieren
> des Programms den Speicher freigibt. Ist da mein Denkfehler?

Das ist zwar richtig aber ganz schlechter Stil. Man sollte sich 
angewöhnen sowas sauber zu machen. Aus dem main() wird vieleicht auch 
mal eine normale Funktion, die von einem anderen Programm gerufen werden 
kann.

Nichtinitialisierte Pointervariable ist ein heisser Kandidat, das 
erklärt auch unterschiedliches Verhalten auf unterschiedlichen Systemen 
bzw. VMs.

von Peter II (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Man sollte schon alles lesen:
>
> Gerhard Z. schrieb:
>> Die Entwicklungsumgebung habe ich in der virtuellen Windos-Installation.
>> Dort stürzt das Programm aber nicht ab.

richtig, darum habe ich auch schon oben geschrieben, das es dann eine 
remote Debugger gibt, den man nicht installieren muss.

von Karl H. (kbuchegg)


Lesenswert?

Udo Schmitt schrieb:
> Karl Heinz schrieb:
>> Technisch ist das so gelöst, dass malloc etwas mehr Speicher reserviert
>> als angefordert und in diesen Überschussspeicher ein bestimmtes Muster
>> reinschreibt. Bei einem free (bzw beim Aufruf von bestimmten Funktionen)
>> werden diese Speicherbereiche abgesucht, ob das Muster immer noch
>> drinnen steht. Wenn nicht, dann hat in der Zwischenzeit irgendein Code
>> den Speicher überschrieben, obwohl er nicht sollte.
>
> Das ist schön und gut, aber der TO gibt seinen Speicher ja nicht frei
> weil das das Betriebssystem für ihn tut:

Da gibt es auch eine Funktion, mit der man den Checker zwischendurch 
anwerfen kann.

Das Programm in Abschnitte aufteilen, nach jedem Abschnitt prüfen lassen 
und man hat zumindest schon mal eine grobe Vorstellung davon bis wohin 
zumindest an dieser Front noch nichts Auffälliges vorgefallen ist.

von Winfried J. (Firma: Nisch-Aufzüge) (winne) Benutzerseite


Lesenswert?

klassische Fehlersuche halt

Namaste

von murkser (Gast)


Lesenswert?

Dependency Walker, depends.exe, Microsoft

Debugging Tools for Windows aus dem SDK (Eruierung, Analyse)

Beide Tools kosten nichts und funktionieren sehr gut.

von Peter II (Gast)


Lesenswert?

murkser schrieb:
> Dependency Walker, depends.exe, Microsoft

Wie hilft diese denn bei den Problem weiter?

von Mark B. (markbrandis)


Lesenswert?

Eventuell auch mal mit Clang/LLVM kompilieren. Kost ebenfalls nichts und 
zwei Compiler sehen mehr als einer.

Wenn man ein Tool zur statischen Codeanalyse hat, sollte man dieses 
natürlich mal über den Code laufen lassen. Die Tools die was taugen 
kosten aber nicht selten auch (deutlich) was.

von murkser (Gast)


Lesenswert?

Peter II schrieb:
> murkser schrieb:
>> Dependency Walker, depends.exe, Microsoft
>
> Wie hilft diese denn bei den Problem weiter?

>> Jetzt zu meiner Frage: Wie kann ich am besten unter Windows den Fehler
>> einkreisen.

Dependency Walker, depends.exe, Microsoft

   zeigt u.a. Abhängigkeiten ...


Debugging Tools for Windows aus dem SDK (Eruierung, Analyse)

   Monitor in Echtzeit mit detailliertem Protokoll

von Mark B. (markbrandis)


Lesenswert?

Ansonsten noch prüfen:

1.) Werden alle Variablen und Arrays zu Beginn des Programms richtig 
initialisiert?
2.) Werden sie auch während der Laufzeit nochmal neu initialisiert, wenn 
dies erforderlich ist?
2.) Werden alle Zeiger richtig initialisiert?
3.) Werden alle Zeiger ernsthaft richtig initialisiert?
4.) Werden alle Zeiger jetzt wirklich ernsthaft richtig und dreifach 
überprüft korrekt initialisiert? :-)

90% aller Abstürze in C-Programmen rühren von Zugriffen auf Zeigern her, 
die auf etwas Ungültiges verweisen. So pflegte es unser Informatik-Prof 
zu sagen. Der Mann hatte in 90% aller Fälle Recht. ;-)

Ach ja! Alle Compiler-Warnungen müssen untersucht und in der Regel auch 
behoben werden. Guter Code zeichnet sich unter anderem dadurch aus, dass 
er ohne jede Warnung kompiliert.

: Bearbeitet durch User
von Gerhard Z. (germel)


Lesenswert?

So, sorry, dass ich so lang nicht geantwortet habe, war sehr 
beschäftigt.

Habe jetzt mal valgrind angeschmissen und hätte gerne Hilfe. Ich 
versuche die Fehler aufzuarbeiten in der Reihenfolge, in der sie 
valgrind rausschreibt. Zunächst ist offensichtlich etwas in meinem 
Antialiasing Tiefpass zu bemäkeln (muss die Wavedaten von 48000 auf 3250 
Hz runtersamplen). Zunächst mal der Code des Filters:

Die filter.h Datei:
1
#ifndef FILTER_H_
2
#define FILTER_H_
3
4
typedef struct
5
{
6
   double A[6];
7
   double B[6];
8
   double State[4];
9
} FILTERSTATE_t;
10
11
extern FILTERSTATE_t *LPF24dB_init(float Samplerate, float Frequency, float PassbandRipple );
12
extern double LPF24dB(FILTERSTATE_t *f, double Input);
13
extern void LPF24dB_free(FILTERSTATE_t *f);
14
15
#endif /* FILTER_H_ */

und dann filter.c:
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <math.h>
4
#include "filter.h"
5
6
FILTERSTATE_t *LPF24dB_init(float Samplerate, float Frequency, float PassbandRipple )
7
{
8
  double K, sg, cg;
9
  double Coeff[4];
10
  FILTERSTATE_t *f;
11
  int i;
12
13
  f=malloc(sizeof(f));
14
  if (f==NULL) return(f);
15
16
  K = tan(M_PI * Frequency / Samplerate);
17
18
  sg = sinh(PassbandRipple);
19
  cg = cosh(PassbandRipple);
20
  cg *= cg;
21
22
  Coeff[0] = 1 / (cg-0.85355339059327376220042218105097);
23
  Coeff[1] = K * Coeff[0]*sg*1.847759065022573512256366378792;
24
  Coeff[2] = 1 / (cg-0.14644660940672623779957781894758);
25
  Coeff[3] = K * Coeff[2]*sg*0.76536686473017954345691996806;
26
27
  K *= K; // (just to optimize it a little bit)
28
29
  f->A[0]  = 1/(Coeff[1]+K+Coeff[0]);
30
  f->A[1] = 2*(Coeff[0]-K)*f->A[0];
31
  f->A[2] = (Coeff[1]-K-Coeff[0])*f->A[0];
32
  f->B[0] = f->A[0]*K;
33
  f->B[1] = 2*f->B[0];
34
  f->B[2] = f->B[0];
35
36
  f->A[3]  = 1/(Coeff[3]+K+Coeff[2]);
37
  f->A[4] = 2*(Coeff[2]-K)*f->A[3];
38
  f->A[5] = (Coeff[3]-K-Coeff[2])*f->A[3];
39
  f->B[3] = f->A[3]*K;
40
  f->B[4] = 2*f->B[3];
41
  f->B[5] = f->B[3];
42
  for (i=0; i<4; i++)
43
    f->State[i]=0;
44
  return(f);
45
}
46
47
double LPF24dB(FILTERSTATE_t *f, double Input)
48
{
49
  double Stage1, Output;
50
  Stage1 = f->B[0]*Input + f->State[0];
51
  f->State[0] = f->B[1]*Input + f->A[1]*Stage1 + f->State[1];
52
  f->State[1] = f->B[2]*Input + f->A[2]*Stage1;
53
  Output = f->B[3]*Stage1 + f->State[2];
54
  f->State[2] = f->B[4]*Stage1 + f->A[4]*Output + f->State[3];
55
  f->State[3] = f->B[5]*Stage1 + f->A[5]*Output;
56
  return(Output);
57
}
58
59
void LPF24dB_free(FILTERSTATE_t *f)
60
{
61
 free(f);
62
}

Im Programm erfolgt die Initialisierung so:
1
  static FILTERSTATE_t *f;
2
  f=LPF24dB_init(48000, 800 /* corner frequency */, 1.0 /* passband ripple */);

und später:
1
  double Rvalue;
2
  Rvalue = irgendwas;
3
  Rvalue=LPF24dB(f, Rvalue);


valgrind schmeißt mir als erstes folgenden Fehler raus:
==2429== Invalid write of size 8
==2429==    at 0x804E11E: LPF24dB_init (filter.c:30)
==2429==    by 0x8049F61: EngineNextSampleFromFile (fake_ecu.c:246)
==2429==    by 0x804B502: DA_Exhaust_AD (fake_ecu.c:619)
==2429==    by 0x804BB51: main (ednc_sim.c:161)

Wobei folgendes die Zeile 30 ist:
1
  f->A[0]  = 1/(Coeff[1]+K+Coeff[0]);

Was mach ich falsch?
Gerhard

von Arc N. (arc)


Lesenswert?

Gerhard Z. schrieb:
> typedef struct
> {
>    double A[6];
>    double B[6];
>    double State[4];
> } FILTERSTATE_t;
>   ...
>   FILTERSTATE_t *f;
>   ...
>   f=malloc(sizeof(f));
>   if (f==NULL) return(f);

Was liefert sizeof(f) zurück? Die Länge des Structs oder die Länge eines 
Zeigers auf einen Struct?

von Gerhard Z. (germel)


Lesenswert?

Hatte ich auch schon als möglichen Fehler im Auge, aber
1
  f=malloc(sizeof(FILTERSTATE_t));

gibt die gleichen Fehler in valgrind.

von Gerhard Z. (germel)


Lesenswert?

Oh nein, Kommando zurrück. Hatte es in der falschen filter.c geändert. 
Ja, muss natürlich
1
f=malloc(sizeof(FILTERSTATE_t));

heißen:
1
printf("%i\n", sizeof(FILTERSTATE_t));
2
printf("%i\n", sizeof(f));

gibt:
128
4

Vielen Dank schon mal!

Gerhard

PS: bin halt eigentlich Pascal Programmierer. Da fühl ich mich deutlich 
wohler.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Du kannst auch
1
sizeof *f
schreiben.

von Gerhard Z. (germel)


Lesenswert?

Final:

Das war's, jetzt läuft es in Windows auch anstandslos! Ich danke euch 
noch mal für eure Hilfen. Wir können den Faden schließen.

Etwas erstaunlich ist - valgrind zeigt mir jetzt keinen Fehler mehr in 
meinem Code, aber offensichtlich in libc-start.c?!


==3609== Conditional jump or move depends on uninitialised value(s)
==3609==    at 0x4079D77: log10f (w_log10f.c:28)
==3609==    by 0x40BA934: (below main) (libc-start.c:260)
==3609==
==3609== Conditional jump or move depends on uninitialised value(s)
==3609==    at 0x40EAF1D: __printf_fp (printf_fp.c:404)
==3609==    by 0x40E638C: vfprintf (vfprintf.c:1654)
==3609==    by 0x40EF7DE: fprintf (fprintf.c:32)
==3609==    by 0x40BA934: (below main) (libc-start.c:260)
==3609==
usw.

Oder ist das was, was ich noch irgendwo verbockt habe?

Gerhard

von Arc N. (arc)


Lesenswert?

valgrind --track-origins=yes
http://valgrind.org/docs/manual/mc-manual.html
"Controls whether Memcheck tracks the origin of uninitialised values. By 
default, it does not, which means that although it can tell you that an 
uninitialised value is being used in a dangerous way, it cannot tell you 
where the uninitialised value came from."

von Mark B. (markbrandis)


Lesenswert?

Ein Wort noch zu den Programmierkonventionen:

1
FILTERSTATE_t *LPF24dB_init(float Samplerate, float Frequency, float 
2
PassbandRipple )

Hier hat man nahezu alles richtig gemacht, was die Benennung der 
Variablen bzw. der Funktion betrifft.

Und dann sowas:

1
double K, sg, cg;
2
FILTERSTATE_t *f;
3
4
f->B[0] = f->A[0]*K;
5
f->B[1] = 2*f->B[0];
6
f->B[2] = f->B[0];
7
 
8
f->B[3] = f->A[3]*K;
9
f->B[4] = 2*f->B[3];
10
f->B[5] = f->B[3];

Das ist Code von der Sorte, den später keiner vernünftig warten kann. 
Warum hat alle Welt solche Angst vor selbst sprechenden Bezeichnern und 
vor vernünftig eingesetzten Kommentaren?

Früher gab es die Argumente:
-Speicherplatz (für den Sourcecode und für Kommentare) ist knapp, also 
verwendet man so wenige Buchstaben wie möglich für die Bezeichner und 
spart sich Kommentare am besten gleich ganz
-Mit kürzeren Namen für Funktionen und Variablen spart man sich 
Tipparbeit

Heutzutage gelten beide Argumente schon sehr lange nicht mehr. 
Speicherplatz ist in Hülle und Fülle vorhanden. Jeder moderne Texteditor 
beherrscht Auto-Vervollständigung aus dem Effeff. Es gibt keinen 
vernünftigen Grund mehr, Bezeichner wie "f" oder "a" oder so etwas in 
der Art zu verwenden. Einzige legale Ausnahme: Die typischen 
Indexvariablen wie i und j bei Schleifen.

C bietet einem 31 Buchstaben pro Bezeichner, also nutze man sie verdammt 
noch mal! ;-)

Der Kommentar hier ist nutzlos, ja sogar irreführend:
1
K *= K; // (just to optimize it a little bit)

Später weiß kein Mensch mehr, warum um alles in der Welt das Quadrieren 
eines Wertes "eine kleine Optimierung" darstellen soll. Das ist aber 
gerade der Sinn eines Kommentars: Zu erläutern, warum man etwas so 
macht wie man es macht.

Ein möglicher Test für Code-Qualität ist:
Man lese seinen eigenen Code ein Jahr, nachdem man ihn geschrieben hat. 
Kann man sofort und intuitiv verstehen, was man da verzapft hat? :-)

: Bearbeitet durch User
von Hans (Gast)


Lesenswert?

Nebenbei bemerkt bräuchte man kein malloc (und kein LPF24dB_free), wenn 
der Aufrufer der Funktion LPF24dB_init einen Zeiger auf ein 
FILTERSTATE_t mitgeben würde.

1
void LPF24dB_init(FILTERSTATE_t *f, float Samplerate, float Frequency, float PassbandRipple)
2
{
3
  double K, sg, cg;
4
  double Coeff[4];
5
  int i;
6
7
  K = tan(M_PI * Frequency / Samplerate);
8
9
  sg = sinh(PassbandRipple);
10
  cg = cosh(PassbandRipple);
11
  cg *= cg;
12
13
  // [...]
14
}

FILTERSTATE_t kann der Aufrufer je nach Bedarf statisch oder dynamisch 
allozieren. In Deinem Fall würde es statisch fast gleich aussehen:
1
  static FILTERSTATE_t f;
2
  f=LPF24dB_init(&f, 48000, 800 /* corner frequency */, 1.0 /* passband ripple */);
3
4
  // [...]
5
  double Rvalue;
6
  Rvalue = irgendwas;
7
  Rvalue=LPF24dB(&f, Rvalue);

von Hans (Gast)


Lesenswert?

Korrektur: Die Zuweisung an f brauchts natürlich nicht mehr ...
1
static FILTERSTATE_t f;
2
LPF24dB_init(&f, 48000, 800 /* corner frequency */, 1.0 /* passband ripple */);

von hauspapa (Gast)


Lesenswert?

> if (f==NULL) return(f);

Kurze Rückfrage von einem Programmieranfänger:
if Anweisung ohne {} geht sowas?

Danke
hauspapa

von Mark B. (markbrandis)


Lesenswert?

hauspapa schrieb:
>> if (f==NULL) return(f);
>
> Kurze Rückfrage von einem Programmieranfänger:
> if Anweisung ohne {} geht sowas?

Ja es geht, ist aber nicht empfohlen laut z.B. MISRA-Richtlinien.

von Peter II (Gast)


Lesenswert?

hauspapa schrieb:
> if Anweisung ohne {} geht sowas?

ja, die {} braucht man nur um mehre Anweisungen zu schreiben. Aber ist 
es empfohlen immer die {} zu verwenden.

von Gerhard Z. (germel)


Lesenswert?

hauspapa schrieb:
>> if (f==NULL) return(f);
>
> Kurze Rückfrage von einem Programmieranfänger:
> if Anweisung ohne {} geht sowas?

hatte mir das in Pascal angewöhnt, weil dort mir ein begin ... end; 
(anstatt { ... } in C) für eine Anweisung als Overkill vorkam. Aber 
natürlich gibt es eine gewisse Gefahr mit der Schreibweise. Daher halte 
ich die Anweisung bei Nichtklammerung nach Möglichkeit immer in der 
gleichen Zeile, um nicht durch z.B. Einrückung in der nächsten Zeile 
vorzutäuschen, man könnte einfach weitere Zeilen dem if zuordnen. (Geht 
nur leider nicht, wenn man die if clause debuggen will).

An die Anderen: Weiterhin Danke für eure Tips zum Programierstiel. Werde 
sie versuchen, weitgehend einzuarbeiten.

Gerhard

von Rolf M. (rmagnus)


Lesenswert?

Mark Brandis schrieb:
> Es gibt keinen vernünftigen Grund mehr, Bezeichner wie "f" oder "a" oder so
> etwas in der Art zu verwenden.

Doch, es gibt einen: Man bildet eine mathematische Funktion nach, bei 
der die Namen auch so sind. Vergleiche auch x und y für Koordinaten. 
Sollte man die etwa KoordinateInHorizontalerRichtung und derlei nennen, 
nur damit sich nicht nur ein Zeichen lang sind?

> Man lese seinen eigenen Code ein Jahr, nachdem man ihn geschrieben hat.
> Wenn man ihn nicht sofort und intuitiv verstehen kann, dann hat man
> nicht gut programmiert.

Toll. Dann weiß ich, daß ich vor einem Jahr schlechten Code geschrieben 
habe. Hätte ich das mal vor einem Jahr gewusst...

von Georg A. (georga)


Lesenswert?

> Es gibt keinen vernünftigen Grund mehr, Bezeichner wie "f" oder "a" oder
> so etwas in der Art zu verwenden.

So pauschal ist das doch völliger Unfug von Gutmenschenprogrammieren, 
die am Abend nur dann beruhigt einschlafen können, wenn sie ein goto 
durch 10 ifs und try-catch'es ersetzen konnten.
1
FilterStatus->KoeffizientB[0] = FilterStatus->KoeffizientA[0]*KonstanteVerstaerkung;
2
FilterStatus->KoeffizientB[1] = 2*FilterStatus->KoeffizientB[0];
3
FilterStatus->KoeffizientB[2] = FilterStatus->KoeffizientB[0];
4
 
5
FilterStatus->KoeffizientB[3] = FilterStatus->KoeffizientA[3]*KonstanteVerstaerkung;
6
FilterStatus->KoeffizientB[4] = 2*FilterStatus->KoeffizientB[3];
7
FilterStatus->KoeffizientB[5] = FilterStatus->KoeffizientB[3];

... ist ja auch soooo vieeeel besser zu lesen.

von Mark B. (markbrandis)


Lesenswert?

Rolf Magnus schrieb:
> Toll. Dann weiß ich, daß ich vor einem Jahr schlechten Code geschrieben
> habe. Hätte ich das mal vor einem Jahr gewusst...

Ein richtig guter Programmierer zu werden dauert mindestens mehrere 
Jahre, wenn nicht gar ein Jahrzehnt oder noch länger. Wer etwas anderes 
behauptet, der lügt. ;-)


Georg A. schrieb:
> ... ist ja auch soooo vieeeel besser zu lesen.

Ich find's besser zu lesen. Entweder so, oder aber man schreibt direkt 
zu der Funktion einen Kommentar hinzu, der die Bezeichner erläutert:

1
/*
2
f: Filterstatus
3
A: Filterkoeffizient A
4
B: Filterkoeffizient B
5
K: Konstante Verstaerkung
6
*/

Und goto ist ganz arg böse! Ja. Da stirbt jedesmal ein kleines 
Hundebaby, wenn man es benutzt.

Zugegeben gibt es viel wildere und unverständlichere Beispiele als das 
hier mit dem digitalen Filter. Wenn ich einen Euro hätte für jedes Mal, 
bei dem ein Programmierer unverständliche Bezeichner verwendet hat, dann 
bräuchte ich nicht mehr arbeiten gehen.

: Bearbeitet durch User
von Arc N. (arc)


Lesenswert?

Mark Brandis schrieb:
> Ich find's besser zu lesen. Entweder so, oder aber man schreibt direkt
> zu der Funktion einen Kommentar hinzu, der die Bezeichner erläutert:

Ja und nein...
Das Problem ist, dass gerade im Mathe/Physikbereich mehr oder weniger 
alles nur einen Buchstaben hat, wenn auch stellenweise mit Dach, 
Schlange, Unterstrich, Überstrich, lateinische/griechische/irgendwas 
Großbuchstaben/Kleinbuchstaben/Symbole und das je nach Kontext/Fach ein 
und dasselbe Symbol was anderes bedeuten kann.
Aber...
1. Will zumindest ich so was möglichst 1:1 übernehmen, damit es leichter 
mit dem Original vergleichbar ist
2. Habe ich es lieber wenn ich die gesamte Formel auf einmal sehen kann 
ohne zu scrollen/Augen/Kopf unnötig bewegen zu müssen (ebenso bei 
Methoden/Funktionen, gut das es noch Monitore mit Pivot-Funktion bzw. im 
Nicht-Konsumentenformat gibt).

> Und goto ist ganz arg böse! Ja. Da stirbt jedesmal ein kleines
> Hundebaby, wenn man es benutzt.

Oder um in dem Bild zu bleiben: Verhungert im Klammerndschungel der 
vielen, vielen u.U. nötigen Ifs, whiles etc.

von Rolf M. (rmagnus)


Lesenswert?

Also so lange Namen, die sich dann aber nur in einem Zeichen, und dann 
auch noch erst dem letzten, unterscheiden, finde ich persönlich schwerer 
zu lesen, da schlechter unterscheidbar. Da muß ich viel länger drauf 
schauen, um an jeder Stelle zu erkennen, ob jetzt A oder B gemeint ist.

Arc Net schrieb:
> gut das es noch Monitore mit Pivot-Funktion bzw. im Nicht-Konsumentenformat
> gibt).

Ich habe letztens festgestellt, daß es einen Monitor in 1:1 gibt, mit 
1920x1920 Pixeln Auflösung.

Mark Brandis schrieb:
> Ein richtig guter Programmierer zu werden dauert mindestens mehrere
> Jahre, wenn nicht gar ein Jahrzehnt oder noch länger.

Das ist mir bewußt, denn ich bin schon eine ganze Weile bei "oder noch 
länger". Man kann aber auch nur dann ein "richtig guter Programmierer" 
werden, wenn man sich von so leeren Floskeln wie:

Mark Brandis schrieb:
> Und goto ist ganz arg böse!

trennt und Dinge selbst hinterfragt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Ich habe letztens festgestellt, daß es einen Monitor in 1:1 gibt, mit
> 1920x1920 Pixeln Auflösung.

Ja. *Endlich!*. Allerdings ist die Preisvorstellung, die die wenigen 
Onlinehändler, die ihn verkaufen, noch jenseits von gut und böse:

http://www.heise.de/preisvergleich/eizo-flexscan-ev2730q-schwarz-a1199579.html

von Dirk B. (dirkb2)


Lesenswert?

Rolf Magnus schrieb:
> Ich habe letztens festgestellt, daß es einen Monitor in 1:1 gibt, mit
> 1920x1920 Pixeln Auflösung.

Es geht doch :-)
Schade, dass er durch den Preis ein Nischenprodunkt bleibt.

Und der Trend geht ja zu 4K.

von Rolf Magnus (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Ja. *Endlich!*. Allerdings ist die Preisvorstellung, die die wenigen
> Onlinehändler, die ihn verkaufen, noch jenseits von gut und böse:

So wenige sind das doch eigentlich nicht. Der Preis wird sich vermutlich 
zusammensetzen aus der Tatsache, daß der Monitor von Eizo ist (die schon 
immer teuer waren) und daraus, daß die Stückzahlen vermutlich eher 
gering sind.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Rolf Magnus schrieb:
> Der Preis wird sich vermutlich zusammensetzen aus der Tatsache, daß der
> Monitor von Eizo ist (die schon immer teuer waren) und daraus, daß die
> Stückzahlen vermutlich eher gering sind.

Der Monitor ist neu und erst seit Januar überhaupt auf dem Markt.

Da --abgesehen von einer Produktankündigung im Dezember-- nirgends etwas 
über diesen Monitor verlautbart wurde, es von Eizo auch keine Reklame 
dafür gibt (bzw. zu geben scheint), ist die Marktdurchdringung auch eher 
überschaubar.

Reduziert man die Händler, die den Monitor gelistet haben, auf die Menge 
der Händler, die den Monitor tatsächlich vorrätig haben, wird die Liste 
auch deutlich übersichtlicher -- das sind dann nämlich nur noch vier.

von Mark B. (markbrandis)


Lesenswert?

Rolf Magnus schrieb:
> Das ist mir bewußt, denn ich bin schon eine ganze Weile bei "oder noch
> länger". Man kann aber auch nur dann ein "richtig guter Programmierer"
> werden, wenn man sich von so leeren Floskeln wie:
>
> Mark Brandis schrieb:
>> Und goto ist ganz arg böse!
>
> trennt und Dinge selbst hinterfragt.

Zeig mir bitte ein Beispiel, in dem ein goto die beste mögliche Lösung 
darstellt. Ich bin gespannt :-)

von Andreas (Gast)


Lesenswert?

Mark Brandis schrieb:
> Zeig mir bitte ein Beispiel, in dem ein goto die beste mögliche Lösung
> darstellt. Ich bin gespannt :-)

Rausspringen aus verschachtelten Schleifen (aus Performancegründen).

von Mark B. (markbrandis)


Lesenswert?

Andreas schrieb:
> Mark Brandis schrieb:
>> Zeig mir bitte ein Beispiel, in dem ein goto die beste mögliche Lösung
>> darstellt. Ich bin gespannt :-)
>
> Rausspringen aus verschachtelten Schleifen (aus Performancegründen).

Hierzu darf ich stackoverflow.com zitieren:

"Nesting lots of loops is usually a code smell all it's own. Unless you 
are doing, like, 5-dimensional array multiplication, it's hard to 
picture a situation where some of the inner loops couldn't be usefully 
extracted into smaller functions. Like all rules of thumb, there are a 
handful of exceptions I suppose."

Quelle:
http://stackoverflow.com/questions/46586/goto-still-considered-harmful#comment959380_47472

: Bearbeitet durch User
von Arc N. (arc)


Lesenswert?

Mark Brandis schrieb:
> Andreas schrieb:
>> Mark Brandis schrieb:
>>> Zeig mir bitte ein Beispiel, in dem ein goto die beste mögliche Lösung
>>> darstellt. Ich bin gespannt :-)
>>
>> Rausspringen aus verschachtelten Schleifen (aus Performancegründen).
>
> Hierzu darf ich stackoverflow.com zitieren:
>
> "Nesting lots of loops is usually a code smell all it's own. Unless you
> are doing, like, 5-dimensional array multiplication, it's hard to
> picture a situation where some of the inner loops couldn't be usefully
> extracted into smaller functions. Like all rules of thumb, there are a
> handful of exceptions I suppose."
>
> Quelle:
> 
http://stackoverflow.com/questions/46586/goto-still-considered-harmful#comment959380_47472

https://www.kernel.org/doc/Documentation/CodingStyle

The rationale for using gotos is:
- unconditional statements are easier to understand and follow
- nesting is reduced
- errors by not updating individual exit points when making
    modifications are prevented

(der letzte dort noch aufgeführte Punkt ist hier absichtlich nicht mit 
aufgeführt)

von Mark B. (markbrandis)


Lesenswert?

Arc Net schrieb:
> www.kernel.org/doc/Documentation/CodingStyle

Gilt das auch für Anwendungsprogrammierer? :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.