Forum: Compiler & IDEs Debug Funktion in C Programm einbauen


von Be M. (bemi)


Lesenswert?

Hallo,

und noch eine Frage: Ich möchte eine Debugfunktion schreiben, die Trace 
Daten sendet.
1
Trace(unsigned char byte) {
2
...
3
..
4
...
5
}
6
7
void main() {
8
  ...
9
  ....
10
  Trace(7)
11
  ....
12
  ....
13
}

Nun soll es einen Compilerschalter geben.
1
void main() {
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(unsigned char byte) {
2
#ifdef _debug
3
...
4
..
5
...
6
#endif
7
}
8
9
void main() {
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

von Uhu U. (uhu)


Lesenswert?

> 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.

von Walter Schmied (Gast)


Lesenswert?

Hallo,

es bleibt keine "leere Funktion" übrig. Sobalb die Funktion "leer" ist 
wird sie von modernen Compilern einfach wegoptimiert.

Ciao

von Be M. (bemi)


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Be M. (bemi)


Lesenswert?

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

von Simon K. (simon) Benutzerseite


Lesenswert?

Namen mit "_" oder "__" am Anfang solltest du generell nicht verwenden.*


*Habe ich gehört. Weiß nicht, ob das jetzt auf den GCC zutrifft?

von Uhu U. (uhu)


Lesenswert?

Ja, das ist eine allgemeine Konvention für C.

von Be M. (bemi)


Lesenswert?

Gilt das auch für C++?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.)

von Rolf Magnus (Gast)


Lesenswert?

>> Ü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.

von Uhu U. (uhu)


Lesenswert?

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!

von Rolf Magnus (Gast)


Lesenswert?

> 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.

von Uhu U. (uhu)


Lesenswert?

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 :-)

von Be M. (bemi)


Lesenswert?

Bei Microsoft sieht das z.B. so aus:
1
#ifdef UNICODE
2
#define TextOut  TextOutW
3
#else
4
#define TextOut  TextOutA
5
#endif // !UNICODE

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Be M. (bemi)


Lesenswert?

Gute Idee, werde ich einbauen.

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.