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
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.
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.
Karl Heinz schrieb: > Klingt nach irgendeinem Stack Überschreiber. Evtl. ist auch der Stack zu klein.
Gast
#4059343
einfach mal mit dem gdb unter Windows starten?
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
Gast
#4059358
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.
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
Gast
#4059402
Gerhard Z. schrieb: > Noch irgend eine Idee? hast du mehre Threads? Willst du uns den quellcode mal zeigen?
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
Gast
#4059433
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
Gast
#4059448
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.
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.
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
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
Gast
#4059524
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
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
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...
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.
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)
Gast
#4059677
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.
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
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
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.
Gast
#4059755
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.
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.
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.
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.
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.
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.
Gast
#4059898
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.
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.
klassische Fehlersuche halt Namaste
Gast
#4060266
Dependency Walker, depends.exe, Microsoft Debugging Tools for Windows aus dem SDK (Eruierung, Analyse) Beide Tools kosten nichts und funktionieren sehr gut.
Gast
#4060274
murkser schrieb: > Dependency Walker, depends.exe, Microsoft Wie hilft diese denn bei den Problem weiter?
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.
Gast
#4060280
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
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.
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
und dann filter.c:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
Im Programm erfolgt die Initialisierung so:
1 | |
2 | |
und später:
1 | |
2 | |
3 | |
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 | |
Was mach ich falsch? Gerhard
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?
Hatte ich auch schon als möglichen Fehler im Auge, aber
1 | |
gibt die gleichen Fehler in valgrind.
Oh nein, Kommando zurrück. Hatte es in der falschen filter.c geändert. Ja, muss natürlich
1 | |
heißen:
1 | |
2 | |
gibt: 128 4 Vielen Dank schon mal! Gerhard PS: bin halt eigentlich Pascal Programmierer. Da fühl ich mich deutlich wohler.
Du kannst auch
1 | |
schreiben.
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
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."
Ein Wort noch zu den Programmierkonventionen:
1 | |
2 | |
Hier hat man nahezu alles richtig gemacht, was die Benennung der Variablen bzw. der Funktion betrifft. Und dann sowas:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
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 | |
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? :-)
Gast
#4062563
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Gast
#4062568
Korrektur: Die Zuweisung an f brauchts natürlich nicht mehr ...
1 | |
2 | |
Gast
#4062622
> if (f==NULL) return(f);
Kurze Rückfrage von einem Programmieranfänger:
if Anweisung ohne {} geht sowas?
Danke
hauspapa
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.
Gast
#4062624
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.
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
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...
> 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 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
... ist ja auch soooo vieeeel besser zu lesen.
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 | |
3 | |
4 | |
5 | |
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.
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.
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.
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
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.
Gast
#4063272
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.
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.
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 :-)
Gast
#4063867
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).
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
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)
Arc Net schrieb: > www.kernel.org/doc/Documentation/CodingStyle Gilt das auch für Anwendungsprogrammierer? :)
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
