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
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.
Martin schrieb:> Wieso bettest du das nicht einfach in eine Funktion?>
1
>voiddebug(char*text,intvalue)
2
>{
3
>#ifdefDEBUG
4
>Serial.print(text);
5
>Serial.print(value);
6
>#endif
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 +/-)
Mit dieser Info wird solltest du in der Lage sein selbst deine Makros zu
bauen.
Zudem ggf. noch relevant sind die Makros:
1
__FILE__
und
1
__LINE__
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
Dr. Sommer schrieb:> #ifdef DEBUG> #define...
Du willst so einen Kruscht doch wohl nicht in einer fertigen,
ausprobierten Quelle drin lassen - oder??!
W.S.
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.).
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
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.
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.
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?
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.
> 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.
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))
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.
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.
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?
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.
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