Hallo,
ich suche schon das halbe Netz aber aber finde nicht Gescheites.
Ich habe keine Lust meinen Code durch
#ifdef DEBUG
Serial.Print.....
#endif
nach fast jeder Zeile oder Codebaschnitt zu versauen. Das ist nachher
unleserlich in der Release Version :-(
Schöner wäre sowas
<Befehle.....>
DBG("Variable =",var) oder wenigstens DBG(Variable);
was dann mit einem einzigen Präprozessor Schwitch entweder mit ein
kompiliert wird oder einfach übergangen.
Kann mir da mal einer helfen?
Gruss,
Christian
Gast
#3252444
Christian J. schrieb: > Kann mir da mal einer helfen? Ähem... du kennst sicherlich den Witz: "woran erkennt man eine helfende Kritik?" Antwort: "Sie beginnt mit den Worten IHNEN WERD ICH HELFEN!..." Ich mach es so, daß ich mir einen Debug-Ringpuffer einrichte, ihn an passenden Stellen mit Debugausgaben fülle und bei passender Gelegenheit in der Grundschleife in main seriell ausgebe. Hat den Vorteil, daß die Debugausgaben auch zeitlich nicht wirklich auftragen, also nicht so sehr intrusiv sind wie ein Debugger. Sowas wie printf halte ich auf nem µC für völlig daneben. Wenn der Code dann läuft, fliegen alle Debugeinträge wieder raus. Ist eben ein bissel Editierarbeit und das Schlaraffenland gibt's weder für dich noch für mich. Ich häng dir mal ne Datei dran, die ich zu sowas verwende. W.S.
Gast
#3252466
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
Gast
#3252467
>#ifdef DEBUG >#define debug(...) Serial.print(_VA_ARGS_) >#else >#define debug(...) >#endif Vieleicht besser so: #ifdef DEBUG #define debug Serial.print #else #define debug(...) #endif
Gast
#3252513
Wieso bettest du das nicht einfach in eine Funktion?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Dann hast du auch nicht mehr so viel zu schreiben, und die Funktion macht garnichts bevor du nicht DEBUG definiert hast!
Martin schrieb: > Wieso bettest du das nicht einfach in eine Funktion? >
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
> > Dann hast du auch nicht mehr so viel zu schreiben, und die Funktion > macht garnichts bevor du nicht DEBUG definiert hast! Aber die Funktion belegt den Speicher immer. --- Christian J. schrieb: > <Befehle.....> > DBG("Variable =",var) oder wenigstens DBG(Variable); Sowas geht (nicht getestet, aber +/-)
1 | |
2 | |
ggf. sicherer, aber warscheinlich minimal langsamer:
1 | |
2 | |
etc. Für dich relevant:
1 | |
wird vom Precompiler ersetzt durch
1 | |
UND
1 | |
entspricht in C, ebenfalls Precompiler.
1 | |
Mit dieser Info wird solltest du in der Lage sein selbst deine Makros zu bauen. Zudem ggf. noch relevant sind die Makros:
1 | |
und
1 | |
welche jeweils durch die aktuelle Datei / Zeile ersetzt werden. Das sind so Dinge die immer schwer zu ergoogeln sind, am besten schaut man sich für sowas Debug Libs an, welche sowas implementieren. Auswendig kann ich dir aber gerade nichts nennen... mfg Andreas
Gast
#3252552
Dr. Sommer schrieb: > #ifdef DEBUG > #define... Du willst so einen Kruscht doch wohl nicht in einer fertigen, ausprobierten Quelle drin lassen - oder??! W.S.
Gast
#3252554
Martin schrieb: > Wieso bettest du das nicht einfach in eine Funktion? Das ist sogar noch besser, aber dann gleich universal:
1 | |
2 | |
3 | |
4 | |
5 | |
Andreas B. schrieb: > Aber die Funktion belegt den Speicher immer. Der Compiler wird sie wegoptimieren wenn sie leer ist.
Gast
#3252557
W.S. schrieb: > Du willst so einen Kruscht doch wohl nicht in einer fertigen, > ausprobierten Quelle drin lassen - oder??! > > W.S. Dieser Kruscht funktioniert gut und wird oft verwendet. Eine Funktion ist aber besser (s.o.).
Gast
#3253189
Hallo, die Sache mit der Funktion scheint mir am sinnvollsten zu sein. Ob da ein Rumpf übrig bleibt, die dauernd angesprungen wird isz mir egal, das sind nur ein paar Ticks. Gruss, Christian
Gast
#3253203
anstelle von
#ifdef DEBUG
#define DBG(...) Serial.print(_VA_ARGS_)
#else
#define DBG(...)
#endif
solltest du:
#ifdef DEBUG
#define DBG(lvl, fmt, args ...)
(DEBUG<0?(lvl)==-DEBUG:DEBUG<=(lvl)&&Serial.print("\nDBG(%s.%s:%d): "
fmt " ",##args))
#else
#define DBG(lvl,...) 1
#endif
Dies, weil du dann in
if (foo==bar) foobar();
ein
if (foo==bar&&DBG("foobar()")) foobar();
machen kannst.
Gast
#3253208
Chris schrieb: > Dies, weil du dann in > if (foo==bar) foobar(); > ein > if (foo==bar&&DBG("foobar()")) foobar(); > machen kannst. sorry das ist krank. Man sollte eh immer mit {} arbeiten. Dann kann man auch lesbaren code schreiben. if ( foo==bar ) { DBG("foobar()"); foobar(); } hat auch den vorteil man kann ein breakpoint innerhalb vom IF setzen.
Gast
#3254053
Interessant, genau gestern hatte ich eine ähnliche Idee, allerdings war mein Stand immer dass es keine Makros mit variabler Parameterzahl gibt. VA_ARGS vom C99 Standard ist irgendwie an mir vorbei gegangen :-) Wieso ist denn die Funktion dem (kürzeren) Makro zu bevorzugen? Weils sicherer ist?
Gast
#3254691
Karlo schrieb: > Wieso ist denn die Funktion dem (kürzeren) Makro zu bevorzugen? > Weils sicherer ist? Weil Funktionen typisiert sind, einen eigenen Scope öffnen, in einem Scope sind (und nicht super-global wie Makros) keine Probleme mit Variablennamen-Kollisionen haben, man im Zweifelsfall einen Pointer darauf bekommen kann, etc. Dank Compiler-Optimierungen sind sie auch nicht weniger effizient. Generell sollte man #defines wo nur möglich vermeiden.
Gast
#3254708
> sorry das ist krank. Man sollte eh immer mit {} arbeiten. Dann kann man > auch lesbaren code schreiben. Ist klar, nur in der Realen Welt hat man speziell Code von anderen zu Instrumentalisieren/Debuggen und da ist man dann für sowas froh. Sicher, man könnte den Code durch ein prettify schicken, nur ... . Ein anderes Beispiel ist: if(sendto(sockfd,&dhcpmsg,sizeof(dhcpmsg),0,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0) die("sendto"); Da kann man einfach sowas schreiben: #define die(id) DBG("abort because no %s",id) && die(id) Wie auch #define sendto(fd,msg,size,src,dst,dsize) DBG("sendto ... )&& sendto(fd,msg,size,src,dst,dsize) um überhaupt rauszufinden, was überhaupt gesendet wird.
Gast
#3254709
Im letzten Beispile sollte man
#define sendto(fd,msg,size,src,dst,dsize) DBG("sendto ... )&&
sendto(fd,msg,size,src,dst,dsize)
so definieren:
#define sendto(fd,msg,size,src,dst,dsize) (DBG("sendto ... ),
sendto(fd,msg,size,src,dst,dsize))
Gast
#3254851
Christian schrieb: > Hallo, > > die Sache mit der Funktion scheint mir am sinnvollsten zu sein. Ob da > ein Rumpf übrig bleibt, die dauernd angesprungen wird isz mir egal, das > sind nur ein paar Ticks. Der Rumpf ist leer wenn kein DEBUG gesetzt ist, das optimiert der compiler normalerweise weg, d.h. es wird die leer Funktion erst gar nicht aufgerufen. Sicherheitshalber mal die Compilereinstellungen checken.
Gast
#3254853
Sean L. schrieb: > Der Rumpf ist leer wenn kein DEBUG gesetzt ist, das optimiert der > compiler normalerweise weg, d.h. es wird die leer Funktion erst gar > nicht aufgerufen. aber nur wenn die funktion in der gleichen C datei steht.
Gast
#3255388
Peter II schrieb: > aber nur wenn die funktion in der gleichen C datei steht. ... oder wenn man mit optimierungen linkt: -flto
Gast
#3255427
Das funktioniert? Modul-Übergreifende Funktionen dürfen doch zwecks Seiteneffekte nicht wegoptimiert werden. Aber woher soll denn der Linker wissen ob die Funktion nun etwas macht oder nicht? Der sieht doch nur, dass das Symbol "print_debug()" verwendet wird. Aber er kann doch nicht einfach einen Sprung in diese Funktion, die der Compiler erzeugt hat, wieder streichen. Gegenteilige Meinungen?
Gast
#3255442
Bei -flto erzeugt der Compiler zusätzlichen Bytecode, der in der Object-File hinterlegt wird. Den kann der Linker anschauen. Dann weiß er, dass er print_debug() rauswerfen darf.
Gast
#3255846
Möp schrieb: > Das funktioniert? Ja, sogar schockierend gut > Modul-Übergreifende Funktionen dürfen doch zwecks Seiteneffekte nicht > wegoptimiert werden. Doch, wenn der Linker das finale Ergebnis des Linkens sieht kann er feststellen ob eine Funktion verwendet wird oder nicht. > Aber woher soll denn der Linker wissen ob die Funktion nun etwas macht > oder nicht? Er guckt in den Code. > Der sieht doch nur, dass das Symbol "print_debug()" verwendet wird. Aber > er kann doch nicht einfach einen Sprung in diese Funktion, die der > Compiler erzeugt hat, wieder streichen. Doch, der vom Compiler erzeugte "GIMPLE"-Code gibt ihm die nötigen Informationen, sodass er leere/unbenutzte Funktionen wegoptimieren kann, nur 1x verwendete Funktionen unabhängig von ihrer Größe komplett inlinen, globale Konstanten in Funktionen inlinen, etc. > Gegenteilige Meinungen? Was zählen denn Meinungen, probier's halt aus
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.