Ich suche ein grep-ähnliches Werkzeug, das man auf eine c/c++-Datei loslassen kann und das dann allen (nicht durch #if ausgeschlossenen) #include-Dateien folgt und die ebenfalls nach dem gesuchten Stichwort durchsucht - das Ganze beliebig tief geschachtelt. Kennt jemand was in der Art?
Du kannst ja deinen Quelltext nur durch den Präprozessor jagen (cpp), ohne anschließend zu compilieren. Dann hast du alles in einer Datei, was sonst durch den Compiler gedreht würde.
Nennt sich moderne IDE. Eclipse sollte sowas bieten, in Java funktioniert sowas wie "Open Declaration" oder "Open Type Hierarchie", "Open Call Hierarchie" einwandfrei. Nachtrag: Gute Editoren wie Notepad++ oder EM-Editor bieten oft auch ungeahnte Möglichkeiten wenn man sich malintensiver mit ihnen beschäftigt.
:
Bearbeitet durch User
Welches Betriebssystem? Ingos Vorschlag ist das was Du brauchst. Wenn Du dann noch einzelnes raus „grepen willst, dann kannst du das unter Linux noch durch sed/awk/grep pipen bis du das gewünschte Ergebnis hast. Grüsse, René
Ingo W. schrieb: > Du kannst ja deinen Quelltext nur durch den Präprozessor jagen (cpp), > ohne anschließend zu compilieren. Dann hast du alles in einer Datei, was > sonst durch den Compiler gedreht würde. Das hilft leider nicht, weil die #defines aufgelöst werden und nur noch deren Wert in der cpp-Ausgabe steht.
René H. schrieb: > Welches Betriebssystem? Linux > Ingos Vorschlag ist das was Du brauchst. Beitrag "Re: grep-ähnliches Werkzeug gesucht"
Weshalb dürfen #defines nicht aufgelöst werden, was ist dein Ziel genau? Nur #includes auflösen? Also einfach rekursiv durch den Code? Grüsse, René
René H. schrieb: > Weshalb dürfen #defines nicht aufgelöst werden, was ist dein Ziel genau? Ich habe ein Problem mit einem #define, dessen Definition auf merkwürdige Weise verschütt geht - die Spuren des Unfalls würden vom Preprozessor verwischt und ich bin so schlau wie vorher. Mit einem grep, der statt durch einen Verzeichnisbaum durch die #include-Hierarchie sucht, könnte man nach dem Symbol suchen und hätte dann vermutlich schnell die Stelle gefunden, an der der Unfall passiert. Lediglich #defines, die in #include-Anweisungen benutzt werden, müssten natürlich genau aufgelöst werden, um den Weg durch die #includes korrekt zu finden.
:
Bearbeitet durch User
Schreib dir doch schnell ein Bash-Skript? Du könntest im ersten File das #define suchen, und falls nicht gefunden suchst du nach #include, nimmst den dateinamen und jagst den wieder durch grep, usw. bis dein #define gefunden ist. Mit einer Kombination aus sed/grep/awk sollte das Problemlos lösbar sein.
Das Ganze ist etwas kompliziert: Ich habe einen Simulator für einen MLT-BT05 Bluetooth Low Energy-Adapter gebastelt, mit dem ich meine avr-Module ohne Änderungen im Code unter Linux testen kann. Das Problem dabei sind die avr-Header in diesen Source-Files. Die trickse ich mit einem kleinen Header aus, der unter der Bedingung #if SIMULATION eingelesen wird. U.a. definiert er die Symbole der Bauart AVR_INTERRUPT_H, die verhindern, dass der Inhalt des entsprechenden avr-Headers wirksam wird. (Das dient normalerweise dazu, Fehler durch das mehrfache #includen eines Headers zu unterdrücken.) Außerdem werden einige Symbole aus den avr-Headern definiert, die für die Simulation gebraucht werden. In der Software, die simuliert werden soll, steht folgende Definition:
1 | enum UARTError { |
2 | UART_Escape = 1, |
3 | UART_DataOverrun = 1 << DOR0, |
4 | UART_FrameError = 1 << FE0, |
5 | UART_ParityError = 1 << UPE0 |
6 | };
|
Die Symbole werden im Simulations-Header definiert als:
1 | #define UPE0 2
|
2 | #define DOR0 3
|
3 | #define FE0 4
|
Nach diesem Header werden die üblichen avr-Header #includet. Das seltsame ist nun, dass der Compiler DOR0 und FE0 kennt, nicht aber UPE0. (Wenn ich die letzte Zeile im enum auskommentiere, gibt es keinen Fehler mehr.) Solche Gurken zu finden, ist wirklich ein ganz übler Job - mit so einem grep-ähnlichen Werkzeug könnte man das stark vereinfachen.
Silvano C. schrieb: > Schreib dir doch schnell ein Bash-Skript? Bei solchen Dingen steckt der Teufel im Detail - das kriegt man erfahrungsgemäß nicht mal eben schnell hin ;-) Bash ist dazu wohl am wenigsten von allen Skriptsprachen geeignet…
Uhu U. schrieb: > Das seltsame ist nun, dass der Compiler DOR0 und FE0 kennt, nicht aber > UPE0. (Wenn ich die letzte Zeile im enum auskommentiere, gibt es keinen > Fehler mehr.) Beantwortet nicht deine Frage, aber: Wenn du die anderen #defines in deinem Simulations-Header auskommentierst, was passiert dann? Sonst: gcc -H probieren... MfG, Arno
Arno schrieb: > Wenn du die anderen #defines in deinem Simulations-Header > auskommentierst, was passiert dann?
1 | error: ‘DOR0’ undeclared here (not in a function) |
2 | error: ‘FE0’ undeclared here (not in a function) |
Wie zu erwarten war. (Die 3 Zeile ist auskommentiert.) Und jetzt wirds ganz komisch: Wenn die 3. Zeile nicht auskommentiert ist, verschwinden die beiden Fehlermelungen und stattdessen wird
1 | error: ‘UPE0’ undeclared here (not in a function) |
angezeigt…
:
Bearbeitet durch User
So, und jetzt kommt der Oberhammer : Ich benutze Code::Blocks 16.01 als IDE. Die habe ich eben beendet und neu gestartet und oh Wunder: Die Simulation compiliert jetzt auch mit nicht auskommentierter 3. Zeile im enum. Wie sowas passieren kann, ist mir völlig schleierhaft.
Wie gesagt, das Problem hat sich durch Neustart von CB in Luft aufgelöst - warum auch immer. Jörg W. schrieb: > Helfen dir die GCC-Optionen -E -dU vielleicht? Wo finde ich denn die Beschreibung dafür? (Im man-Eintrag für gcc ist -d zwar erwähnt (zweimal "see above"), aber die Beschreibung für -d fehlt. OT: Was für ein Vollpfosten hat denn gerade über alle meine Beiträge je einen Miesen vergeben?
:
Bearbeitet durch User
Uhu U. schrieb: > Wo finde ich denn die Beschreibung dafür? (Im man-Eintrag für gcc ist -d > zwar erwähnt (zweimal "see above"), aber die Beschreibung für -d fehlt. https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html#index-dU
Uhu U. schrieb: > Wo finde ich denn die Beschreibung dafür? Ich habe sie in der man page gefunden:
1 | -dCHARS |
2 | … |
3 | U Like D except that only macros that are expanded, or whose |
4 | definedness is tested in preprocessor directives, are |
5 | output; the output is delayed until the use or test of the |
6 | macro; and #undef directives are also output for macros |
7 | tested but undefined at the time. |
:
Bearbeitet durch Moderator
guest schrieb: > Uhu U. schrieb: >> Wo finde ich denn die Beschreibung dafür? (Im man-Eintrag für gcc ist -d >> zwar erwähnt (zweimal "see above"), aber die Beschreibung für -d fehlt. > > https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html#index-dU OK, in der aktuellen man page ist das etwas sinnvoller umformuliert, sodass man direkt nach -dU suchen kann.
Jörg W. schrieb: > guest schrieb: >> Uhu U. schrieb: >>> Wo finde ich denn die Beschreibung dafür? (Im man-Eintrag für gcc ist -d >>> zwar erwähnt (zweimal "see above"), aber die Beschreibung für -d fehlt. >> >> https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html#index-dU > > OK, in der aktuellen man page ist das etwas sinnvoller umformuliert, > sodass man direkt nach -dU suchen kann. Ich hab es über den Index gefunden: https://gcc.gnu.org/onlinedocs/gcc/Option-Index.html
Falls das nicht hilft, müsstest du dir einen Compiler selbst bauen und dann in der Datei libcpp/directives.c halt eine generelle Warnung generieren lassen für jedes #undef, was verarbeitet wird.
Jörg W. schrieb: > Helfen dir die GCC-Optionen -E -dU vielleicht? Ja, die ist bei solchen Problemen wohl nützlich - die Definitionen werden bei Benutzung angezeigt. Wie so ein Problem durch die IDE entstehen kann, ist mir rätselhaft… Ich hatte mich in den letzten Tagen schon öfters mit so komischen Effekten rumgeärgert, die sich dann plötzlich in Luft auflösten. Ganz übel ist. dass CB 16.01 für avr-gcc unter Linux automatisch den include-Pfad /usr/include in die Compileraufrufe einbaut. Das ist zwar leicht zu reparieren - wenn man weiß wie. (Man muss die Einstellung in ~/.config/codeblocks/default.conf reparieren - falls jemand dasselbe Problem hat und sich hierherverlaufen sollte.)
Jörg W. schrieb: > Falls das nicht hilft, müsstest du dir einen Compiler selbst bauen und > dann in der Datei libcpp/directives.c halt eine generelle Warnung > generieren lassen für jedes #undef, was verarbeitet wird. #undef erscheint auch im gcc -E -dU - Listing. Man sollte derartiges also finden können, wenn es denn in den verarbeiteten Quelltexten steht.
:
Bearbeitet durch User
Uhu U. schrieb: > #undef erscheint auch im gcc -E -dU - Listing. Yep, aber wenn du einen modifizierten Compiler gleich Dateinamen und Zeilennummer eines jeden #undef per cpp_error() ausgeben lässt, sollte es sich sehr viel einfacher finden lassen. Der Code steht in einer Funktion namens do_undef(). Im Prinzip musst du vermutlich nur hier:
1 | if (node->type == NT_MACRO) |
2 | {
|
3 | if (node->flags & NODE_WARN) |
4 | cpp_error (pfile, CPP_DL_WARNING, |
5 | "undefining \"%s\"", NODE_NAME (node)); |
die Bedingung "if (node->flags & NODE_WARN)" auskommentieren.
Ich würde auch sagen, dass man hier in die IDE schauen sollte. Folge dem Ratschlag von Udo S.. IDEs kennen den Code und bieten so eine rekursive Suche in den include Dateien eigentlich auch an. Vielleicht geht das auch mit Editoren wie vim und emacs, aber da fragst du besser die, die diese beiden Programme täglich nutzen. Gut möglich, das es für diese auch entsprechende Plugins gibt.
Uhu U. schrieb: > Wie so ein Problem durch die IDE entstehen kann, ist mir rätselhaft… Ich > hatte mich in den letzten Tagen schon öfters mit so komischen Effekten > rumgeärgert, die sich dann plötzlich in Luft auflösten. Vielleicht hat CB beim Build mit einer alten Objektdatei gearbeitet bzw. das Buildsystem die Änderung in der includedatei nicht registriert und daher die Objektdatei nicht aktualisiert, die dafür zuständig war?
Nano schrieb: > IDEs kennen den Code und bieten so eine rekursive Suche in den include > Dateien eigentlich auch an. CB kann Headerdateien mit einem Klick öffnen - aber damit so einem Problem nachgehen? Da kannst du klicken, bis du schwarz wirst…
Es sieht so aus, als sei irgendwo der Wurm in der Hardware: der Memorytest löst kurz nach dem Start einen Reboot aus.
Es wird wohl langsam Zeit, dass Mainboards für normale PCs lernen auch mit ECC-Speicher zurecht zu kommen…
Paritätsbits waren früher™ ja völlig normal. Als man dann vier 9bittige Riegel zu 32 Bit parallel geschaltet hat, konnte man mit den 4 übrigen Bits eine ECC implementieren. Später kamen dann die Sparfüchse … Wir hatten in der DDR so einen Spruch: Spare um jeden Preis – koste es, was es wolle. Genau das passiert halt hier.
Uhu U. schrieb: > Es wird wohl langsam Zeit, dass Mainboards für normale PCs lernen > auch mit ECC-Speicher zurecht zu kommen… Wer bereit ist dafür Geld auszugeben, der kriegt das schon heute. Workstationmainboards im mATX Standard sind jetzt nicht so viel anders und können in der Regel ECC. Bei der CPU kommt es darauf an. Einige normale Skylakes der unteren Klasse z.b. Pentium oder Core i3 unterstützen z.b ECC RAM, wer mehr Leistung benötigt muss zu den Xeons greifen.
Jörg W. schrieb: > Spare um jeden Preis – koste es, was es wolle. Dann habt ihr also Schäuble und Draghi in einer Person quasi vorweg genommen.
Uhu U. schrieb: > Es sieht so aus, als sei irgendwo der Wurm in der Hardware: der > Memorytest löst kurz nach dem Start einen Reboot aus. Zum probieren: "simultaneous reseating of all RAM modules" PC 2 Handbreit über Tischplatte so halten dass das Motherboard parallel zur Tischplatte ist, dann loslassen. Kann gegen Speicherfehler manchmal Wunder bewirken...
Ich musste bei meinem PC schon zweimal das RAM aus und wieder einbauen, damit der PC wieder startete. Meistens war das nach dem Transport.
Bisher startete Linux Mint 17 nach dem Einschalten mit einem Graphischen Bildschirm für die Passphrasen-Eingabe. Seit einigen Tagen kommt stattdessen sofort das Grub-Boot-Menü. Das sind lauter so kleine Hinweise, dass da irgendwo der Holzwurm am Nagen ist. Das mit dem RAM Ein- und Ausbauen ist eine gute Idee.
Nun habe ich die Hardware mal etwas unter die Lupe genommen - das Bild ist verwirrend: Als erste die beiden 8 GB Speicherriegel raus genommen und wieder reingsteckt. Memorytest angeworfen - wieder ist er sofort abgestürzt. Dann die Speicherriegel vertauscht und oh Wunder, der Memorytest lief durch und das ohne Fehler in 2 h. Dabei hat er einen kompletten Durchlauf geschafft und einen zweiten angefangen. Dann mit ESC abgebrochen und versucht, zu booten - ging nicht, Platte nicht erkannt. Platte raus und wieder rein - dasselbe. Erst nach einigen Startversuchen und an den Steckern und Strippen am MB rumnesteln ist es gelungen, ins Bios zu kommen und über das Bootmenü dort die Platte neu auszuwählen. Dann endlich ins grub-Bootmenü und nochmal den Memorytest ausgewählt - wieder stürzt er sofort ab - wohlgemerkt mit vertauschten Speicherriegeln. Nächster Anlauf und Linux gebootet - jetzt läuft die Mühle. Diagnose? Keine Ahnung. Nun fragt sich, was weiter tun.
Uhu U. schrieb: > Diagnose? Keine Ahnung. Nun fragt sich, was weiter tun. Entweder Oszi anwerfen und den Ripple auf der Stromversorgung messen (5V Stby; 3,3V; 5V). Sollte kleiner als 1% der Spannung sein. Oder anderes (funktionierendes) NT zum testen benutzen. Wenn beides nicht mgl. je 1000 µF an diese 3 Spannungen anbringen. Ergebnis mitteilen.
oszi40 schrieb: > CR2032 <2,5V=? Tauschen Hat die noch eine andere Funktion, als die batteriegepufferte RTC zu versorgen?
Das Netzteil hat ohne Last folgende Ripple (jeweils Maximalwerte) 3.3 V: 70 mV (1%: 33 mV) 5 V: 80 mV (1%: 50 mV) 12 V: 60 mV (1%: 120 mV) Das Netzteil ist also augelutscht… Zum Glück habe ich schon vor einiger Zeit ein Reservenetzteil beschafft. --- So, das neue Netzteil ist eingebaut, nur der Memorytest stürzt immernoch sofort ab. Die CR2032 hat noch 3.04 V.
:
Bearbeitet durch User
Uhu U. schrieb: > Das Netzteil ist also augelutscht… Sieht ganz so aus. Uhu U. schrieb: > Zum Glück habe ich schon vor einiger > Zeit ein Reservenetzteil beschafft. Sowas dazuhaben ist genau so empfehlenswert wie noch 1 Pkg. Kaffeefilter im Regal und ein halbes Brot im Gefrierschrank. :)
Uhu U. schrieb: > nur der Memorytest stürzt immernoch > sofort ab. Wie sehen die Elkos um die CPU und bei der RAM-Stromversorgung aus (Beule Oberseite?)? Bei so 6-10 Jahre alten Mainboards musste ich gelegentlich noch 1-3 Elkos zusätzlich zum NT wechseln bis der Spaß wieder stabil lief.
Uhu U. schrieb: > Diagnose? Keine Ahnung. Nun fragt sich, was weiter tun. Vielleicht hat das Mainboard Mikrohaarrisse und Kontakt gibt es nur wenn der Rechner schon etwas gelaufen ist, das Kupfer sich also ausgedehnt hat und den Haarriß aufgrund der Ausdehnung schließt? In dem Fall müsstest du mal den Zustand zwischen kaltem und warmen Rechner testen.
Der Memorytest tuts jetzt plötzlich wieder, sogar, nachdem ich die RAM-Riegel wieder zurückgetauscht habe. Die Elkos sehen gut aus.
Ein VirualBox VM ging in GuruMeditation - da ging irgendwas oberschief. Man konnte sie zwar zurücksetzten, aber nach dem nächsten Boot wiederholte sich das Spiel. Mit zurückgespieltem Backup läuft sie jetzt wieder. Nachtrag: das zurückspielen hat leider doch nichts gebracht - die VM hängt schon wieder. Jetzt soll erstmal der Memorytest gründlich testen. Beim Start ist aufgefallen, dass er jetzt die 3 Caches anzeigt - beim ersten Lauf nach dem RAM-Riegeltausch waren die Stellen auf dem BS leer geblieben - und der Test läuft jetzt deutlich schneller.
:
Bearbeitet durch User
Der Speichertest hat in 8¼ Stunden 3 komplette Duchläufe ohne Fehler geschafft - schneller war das nicht, das schien nur so, weil die Fortschrittsanzeige des Memorytests grob unlinear ist. Das Problem mit der VM ist hartnäckig. Das riecht nicht gut, denn die hat es jahrelang völlig problemlos getan…
:
Bearbeitet durch User
An dem Punkt würde ich jetzt mit einer anderen Festplatte (von einem älteren Backup zurückgespieltes System) oder einem Live-System einige Stunden arbeiten. (Um auszuschließen, daß das aktuelle System durch die Fehler gelitten hat.)
Ich habe das Problem mit der VM im Oracle-Forum beschrieben und das VB-Log mit hochgeladen - mal sehen, was die herausfinden.
Das Problem war eher eines der banaleren Art: Die Hardware-Unterstützung der Virtualisierung im BIOS des Hostsystems war abgeschaltet. Das muss irgendwie durch die Bastelei passiert sein, denn die BIOS-Grundeinstellungen hatte ich überhaupt nicht geöffnet. Nach der Reaktivierung lief die VM wieder. Oracle hat sehr fix reagiert. Mal sehen, wie sich die Kiste jetzt weiter verhält und vielen Dank für die Hilfe.
:
Bearbeitet durch User
Uhu U. schrieb: > Das Problem war eher eines der banaleren Art: ... Es gab zum Glück einen Fehler. Das ist besser als "geht plötzlich wieder", wo dann eine gewisse Unsicherheit im Kopf zurückbleibt. Die Nackenhaare werden sich nun langsam wieder legen und die Röte wird rasch aus dem Gesicht verschwinden. Nun mit etwas süßem die Nerven füttern. :)
Aber nochmal zum Eingangsposting zurück: ich finde die Idee noch immer interessant, den Include-Baum irgendwie interaktiv durchsuchen zu können. Es ist natürlich nett, wenn die eine oder andere IDE sowas bietet, aber wie es der Teufel so will, benutzt man gerade nicht die, die es kann, wenn es braucht. Die ökonomischere Lösung wäre ein Kommandozeilen-Tool wie z.B. grep - das könnten die IDEs dann einfach mit den entsprechenden Parametern aufrufen, statt das Rad neu zu erfinden… In diesem Thread sieht man mal schön, wie der Weg von einem vermeintlichen Quelltextproblem zum Austausch eines Netzteils führen kann. Kann, weil der Fall doch ziemlich selten vorkommt, denn meistens hat man die Gurke ja selbst irgendwo eingebaut…
:
Bearbeitet durch User
Mit "cpp -M" solltest du die Dependencies auflisten können, daraus sollte sich dann eine Liste der zu durchsuchenden Files aufbauen und an ein ganz gewöhnliches grep weiterreichen lassen. Nur so als Bastelansatz.
Diese -M - Liste enthält nur die Abhängigkeiten Header-Files der Quelldatei. Das ist gedacht, um die Abhängigkeiten in einen Makefile einzubauen - bei dem von mir geschilderten Problem bringt das leider gar nichts. Die Idee, so ein Werkzeug mal so eben nebenbei zu "basteln" siehe hier: Beitrag "Re: grep-ähnliches Werkzeug gesucht"
Beitrag #5692092 wurde von einem Moderator gelöscht.
Je nach Aufgabenstellung eignet sich ‘grep’ sogar ganz gut. Andererseits kann man auch mit ‘Universal ctags’ und ‘GNU Global’ gute Ergebnisse erzielen. Wenn es wirklich genau sein soll, was z.B. in meinen Anwendungen meist gar nicht gewünscht ist, musst Du vielleicht mal im LLVM Umfeld nachsehen. Die haben ja eine Reihe von Werkzeugen zur Analyse. Einige Sprachen mit denen ich zu tun habe, haben für sich betrachtet keine “include-Reihenfolge”. Was #ifdef (bzw dessen Pendant) angeht, möchte ich das meist ignorieren, so dass ich alle Stellen angezeigt bekomme, an denen z.B. eine Variable möglicherweise zugewiesen wird. Meist sind die Alternativen ja nicht so zahlreich. Letztlich muss man sich darüber klar sein, dass Tools, die nicht direkt einer Compilersuite entstammen, Fehler im Parser haben, die zu false negatives führen können, also die eigentlich gesuchte Stelle nicht anzeigen. Scheinbar paradoxerweise sind hiervon die cleversten Werkzeuge betroffen, während ‘grep’ einfach nur viele false positives anzeigt. False positives sind aber meist nicht so schlimm, da man die im Kopf leicht wegfiltern kann.
:
Bearbeitet durch User
Marcus H. schrieb: > False positives sind aber meist nicht so schlimm, da man die im Kopf > leicht wegfiltern kann. Wenn du so willst, kannst du auch gleich den Code mit dem Hex-Editor in den Speicher klopfen… Wenn du ein extrem verwirrendes Szenario hast, wie das, von dem ich ausging, dann suchst du nach Mitteln, die den ganzen Mist übersichtlicher machen und willst dich nicht auch noch mit "im Kopf leicht wegfiltern" auseinandersetzen…
Idealerweise hat man natürlich auch keine false positives. Sie sind aber meiner Erfahrung nach immernoch besser als beispielsweise genau die Zuweisung, die sich später als die Ursache eines Fehlers herausstellt, durch einen ungenauen Parser nicht angezeigt zu bekommen. Eigene Erfahrung. YMMV.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.