Hallo,
und noch eine Frage: Ich möchte eine Debugfunktion schreiben, die Trace
Daten sendet.
1
Trace(unsignedcharbyte){
2
...
3
..
4
...
5
}
6
7
voidmain(){
8
...
9
....
10
Trace(7)
11
....
12
....
13
}
Nun soll es einen Compilerschalter geben.
1
voidmain(){
2
...
3
....
4
#ifdef _debug
5
Trace(7)
6
#endif
7
....
8
....
9
}
Das Dumme ist, dass ich hier immer die #ifdef Anweisung schreiben muss,
schöner wäre es, wenn die in der Funktion stünde.
1
Trace(unsignedcharbyte){
2
#ifdef _debug
3
...
4
..
5
...
6
#endif
7
}
8
9
voidmain(){
10
...
11
....
12
Trace(7)
13
....
14
....
15
}
Allerdings bleibt dann eine leere Funktion übrig, wenn ich den Debug
Mode deaktiviere.
Kann man so etwas machen? Was macht der Compiler, wenn er eine leere
Funktion aufrufen soll?
Es würde ja auch noch die Möglichkeit geben, den Funktionsaufruf in ein
Makro zu packen, dass...
1
#ifdef _debug
2
#define _Trace(i) Trace(i)
3
#else
4
#define _Trace(i)
5
#endif
ungefähr so aussähe, allerdings habe ich die Erfahrung gemacht, dass man
in den meisten Entwicklungsumgebungen eine Breakpoints for Makros setzen
kann.
Was ist der beste Weg?
Danke,
Bernd
> in den meisten Entwicklungsumgebungen eine Breakpoints for Makros> setzen kann.
Klemmen bei dir Tastatur und Rechtschreibung???
Ich benutze üblicherweise die Macrolösung. Wenn der Debugger keinen HP
auf den Macro setzen will, dann schalte ich in das ASM-Fenster des
Debuggers um und setze den HP mit Gewalt dorthin, wo ich ihn haben will.
Wenn leere Funktionen im GCC wegoptimiert werden, ist ja alles ok.
@Uhu Uhuhu:
> Klemmen bei dir Tastatur und Rechtschreibung???
Was habe ich falsch gemacht?
Bernd
Bernd M. wrote:
> Wenn leere Funktionen im GCC wegoptimiert werden, ist ja alles ok.
Du kannst dir ein List-File erstellen lassen und nachschauen, ob die
Funktionsaufrufe bzw. die leere Funktion wegoptimiert wurden.
Eine leere externe Funktion wird nicht wegoptimiert, da ja erst der
Linker merkt, welche Funktion wirklich dahinter steht. (Eine
Ausnahme dürfte -fwhole-program -combine sein.) Die Makrovariante
ist eigentlich die Methode der Wahl. Bitte den Makro nicht _Trace
nennen, da dieser Name im implementation namespace liegt.
Üblicherweise werden Makros ja sowieso in Großbuchstaben geschrieben,
mit TRACE() bist du also auf der sicheren Seite.
Nun ja, mit den Namenskonventionen bin ich noch nicht so vertraut.
> Üblicherweise werden Makros ja sowieso in Großbuchstaben geschrieben,> mit TRACE() bist du also auf der sicheren Seite.
Das ist wohl reine Geschmackssache, beim Windows-API ist das auch nicht
wirklich einheitlich.
> Bitte den Makro nicht _Trace nennen, da dieser Name im implementation> namespace liegt.
??? Was heist das? Woher weiß ich, welche Makronamen ich verwenden darf?
Den "_" oder "__" am Anfrang benutze ich eigentlich immer, wenn Makros
oder Funktionen aus meiner Sicht eine Art Compilererweiterung dastellen.
Und Tracefunktionen betrachte ich als Teil der Entwicklungsumgebung und
nicht als Bestandteil des Programms. Wenn es da allerdings Probleme mit
vorhandenen Namen gibt, würde ich sie natürlich anders benennen.
Bernd
Wenn man Namen, die mit einem Unterstrich beginnen, generell meidet,
ist man auf der sicheren Seite. ;-)
Die genauen Regeln lesen sich im Standard ein wenig komplizierter,
da wird nach Namen innerhalb des file scope und lokalen Namen
unterschieden. Für bestimmte Dinge sind Namen, die mit einem
Unterstrich beginnen, für die Applikation gestattet. Namen, die
mit zwei Unterstrichen beginnen, sind in jeder Hinsicht für
Anwenderprogramme tabu.
Ja, echte Compilererweiterungen dürfen (und müssen) derartige
Namen verwenden. Aber: der Sinn liegt ja genau darin, dass du
als Anwendungsprogrammierer einen Satz von Namen benutzen kannst,
bei denen du dich nicht darum kümmern musst, ob sie in Compiler
und/oder Standardbibliothek schon irgendwie anderweitig in Verwendung
sind. ,,Ich betrachte es als eine Compilererweiterung'' ist daher
keine zulässige Aussage im Sinne des Standards. `the implementation'
ist im Standardsinne der Compiler mit seiner Bibliothek, so wie sie
als Tool geliefert werden. (Falls Compiler- und Bibliotheksbauer
nicht eine Einheit sind, müssen diese sich untereinander hinreichend
gut absprechen, um kollisionsfrei zu arbeiten.)
>> Üblicherweise werden Makros ja sowieso in Großbuchstaben geschrieben,>> mit TRACE() bist du also auf der sicheren Seite.>> Das ist wohl reine Geschmackssache, beim Windows-API ist das auch nicht> wirklich einheitlich.
Es ist zumindest eine recht weit verbreitete Konvention, die meiner
Erfahrung nach eher selten nicht beachtet wird. Meistens, wenn man unter
einem Standard-Funktionsnamen ein Makro definieren will.
> Den "_" oder "__" am Anfrang benutze ich eigentlich immer, wenn Makros> oder Funktionen aus meiner Sicht eine Art Compilererweiterung> dastellen.
Du erweiterst den Compiler?
> Und Tracefunktionen betrachte ich als Teil der Entwicklungsumgebung und> nicht als Bestandteil des Programms.
Nun, wo ist sie denn genau eingebaut? Im Compiler? In der Libc? Oder
nicht vieleicht doch im Programm?
> Wenn es da allerdings Probleme mit vorhandenen Namen gibt, würde ich> sie natürlich anders benennen.
Genau deshalb soll man sie ja generell nicht selbst definieren.
@Bernd M. (bemi):
> Gilt das auch für C++?
Für C++ gilt es auch, aber zusätzlich sollte man auch Namen vermeiden,
die an einer beliebigen Stelle zwei aufeinanderfolgende "_" haben.
Und natürlich rassistische, obszöne und politisch inkorrekte Namen...
Namen, deren CAN-CRC größer als 72387 ist, sind übrigens absolut tabu!
Benutzung führt zu sofortigem Führerscheinentzug!
> Und natürlich rassistische, obszöne und politisch inkorrekte Namen...
Sofern diese beim Zusammenspiel mit deinem Code häufig zu
Namenskonflikten führen, wäre das bei dessen Verwendung vermutlich
sinnvoll.
> Namen, deren CAN-CRC größer als 72387 ist, sind übrigens absolut tabu!> Benutzung führt zu sofortigem Führerscheinentzug!
Wie du das in deinen Projekten handhabst, bleibt natürlich dir
überlassen, aber einen Führerscheinentzug durchzusetzen, dürfte
schwierig sein.
Rolf Magnus wrote:
> Wie du das in deinen Projekten handhabst, bleibt natürlich dir> überlassen, aber einen Führerscheinentzug durchzusetzen, dürfte> schwierig sein.
Ist auch nicht nötig, denn CAN-CRC ist ein 16-Bit-Polynom :-)
Und da es meine Makros nur deswegen geben wird, da es offensichtlich
besser ist den ganzen Funktionsaufruf auszublenden, wenn das ganze nicht
im Trace-Mode läuft, werde ich wohl eine ähnliche Schreibweise
verwenden.
Auf den Underscore werden ich NATÜRLICH verzichten ;-) (glaube ich
zumindest)
Grüße,
Bernd
Besser als #ifdef finde ich übrigens #if für solche Dinge.
1
#if DEBUG
2
# define TRACE(...) printf(__VA_ARGS__)
3
#else
4
# define TRACE(...) /* empty */
5
#endif /* DEBUG */
Dann kann man irgendwo in einer zentralen Headerdatei haben:
1
#ifndef DEBUG
2
/* default to non-debug version */
3
# define DEBUG 0
4
#endif
...kann es jedoch jederzeit von der Compiler-Kommandozeile mit
-DDEBUG=0 oder -DDEBUG=1 (oder -DDEBUG=42 :) überschreiben. Wenn
man mehr als nur 0 und 1 nimmt, kann man auch noch verschiedene
debug levels implementieren.