Problem mit vsprintf()
-
Moin,
ich versuche mir mit vsprintf() Formatstrings mit 32 bit ints auszugeben (meine Architektur ist 32 bit, Linux).
Meine Routine ist:
void out(const char* formatString, ...) { static char outBuffer[1024]; va_list listPointer; va_start( listPointer, formatString ); vsprintf( outBuffer, formatString, listPointer ) ; strcat( outBuffer, "\n" ); va_end( listPointer ); showMessage( outBuffer ); }
Mein Problem: Der Aufruf
const int myInt = 10000; out("%d", myInt);
gibt immer 0 zurück. Habe ich was falsch gemacht?
Anmerkungen:
Ich bin mir sicher, dass die Maximallänge nicht erreicht wurde. Das Programm schreibt mit mehreren Threads in die Ausgabe.Über Hilfe würde ich mich sehr freuen!
Gruß,
Johannes
-
Das sieht erst einmal richtig aus. Das einzige was mir komisch vorkommt ist das statische Array, aber das sollte nicht den beschriebenen Fehler verursachen, sofern du nicht mehrere Threads hast. Zeig mal bitte ein vollständiges Beispiel, welches man selber compilieren kann um den Fehler zu sehen.
edit: Oh jetzt ist klar. Ich sollte mal vollständig lesen
Das Programm schreibt mit mehreren Threads in die Ausgabe.
Das ist natürlich der Killer im Zusammenspiel mit einem statischen Array!
-
voidpointer schrieb:
Anmerkungen:
Ich bin mir sicher, dass die Maximallänge nicht erreicht wurde. Das Programm schreibt mit mehreren Threads in die Ausgabe.Ich wollte gerade anmerken, wozu der Puffer denn static ist, denn das kann mit Threads Probleme geben.
voidpointer schrieb:
gibt immer 0 zurück. Habe ich was falsch gemacht?
Gibt 0 zurück? Das ist doch eine void-Funktion? Oder meinst du "gibt 0 aus"? Wie auch immer, so kann ich keinen Fehler erkennen, außer dass du den Zugriff mit mehreren Threads einem Mutex absichern musst.
Edit:
Verdammt, zu spät.. das war wohl die Rache.
-
cooky451 schrieb:
Wie auch immer, so kann ich keinen Fehler erkennen, außer dass du den Zugriff mit mehreren Threads einem Mutex absichern musst.
Die erste Frage die ich stellen würde ist: Warum überhaupt static. Den einzigen "Sinn" für static an der Stelle den ich erkennen kann ist, dass es diesen Fehler provoziert.
Edit:
Verdammt, zu spät.. das war wohl die Rache.Muahuahua! Der Sonntagmorgen gehört mir!
edit: Dafür kann ich heute irgendwie nicht tippen. 3 Edits für 4 Sätze, damit man's lesen kann...
-
Hi,
Muahuahua! Der Sonntagmorgen gehört mir!
nein, ihr liegt beide falsch!
Die statischen Arrays sind auf jeden Fall pro Thread! Ich meinte nur, dass eben mehrere Threads überhaupt etwas auf der Konsole ausgeben.
Es scheint mir nichts mit den Threads zu tun zu haben. Ich habe eher bedenken, ob man vllt Typinformation verliert, wenn man die Parameter in der va_list übergibt...?
Ein selbstkompilierbares Programm? Bitteschön
(Bei mir rekonstruiert es den Fehler natürlich nicht
)
#include <string.h> #include <stdarg.h> #include <stdio.h> void showMessage(const char* const s) { puts(s); } void out(const char* formatString, ...) { static char outBuffer[1024]; va_list listPointer; va_start( listPointer, formatString ); vsprintf( outBuffer, formatString, listPointer ) ; strcat( outBuffer, "\n" ); va_end( listPointer ); showMessage( outBuffer ); } int main() { const int myInt = 987654321; out("%d", myInt); }
Danke für weitere Antworten
-
voidpointer schrieb:
nein, ihr liegt beide falsch!
Die statischen Arrays sind auf jeden Fall pro Thread! Ich meinte nur, dass eben mehrere Threads überhaupt etwas auf der Konsole ausgeben.
Du bist dir da aber ziemlich sicher. Und das nachdem dir zwei Leute gesagt haben, dass dies nicht so ist. Denn static ist eigentlich Schlüsselwort dafür, dass genau dies nicht der Fall ist.
Ein selbstkompilierbares Programm? Bitteschön
(Bei mir rekonstruiert es den Fehler natürlich nicht
)
Natürlich nicht. Bevor du nicht erklärst, wie du ein static Array pro Thread hinbekommst (das wäre nämlich ein ganz schöner Hack), gilt das weiterhin als die Fehlerursache.
edit: Und eine Erklärung, warum überhaupt static, wäre auch schön.
-
Hi,
dass ich mir sicher war, war nicht böse gemeint. Vllt sehe ich es wirklich falsch? Die out-Funktion ist in meinem Fall eine Funktion pro Objekt, also
Thread1::out() und Thread2::out(). Hätte gedacht, dass das da egal ist? (Ich habs mal weggenommen, der Bug besteht weiterhin).Wieso static? Die Ausgabe ist (wirklich) extrem laufzeitkritisch!
Gruß,
Johannes
-
voidpointer schrieb:
dass ich mir sicher war, war nicht böse gemeint. Vllt sehe ich es wirklich falsch? Die out-Funktion ist in meinem Fall eine Funktion pro Objekt, also
Thread1::out() und Thread2::out(). Hätte gedacht, dass das da egal ist? (Ich habs mal weggenommen, der Bug besteht weiterhin).Wie? Was? Objekt? In welcher Sprache bist du? Weißt du überhaupt was static bedeutet?
Wieso static? Die Ausgabe ist (wirklich) extrem laufzeitkritisch!
Unsinn. Was hat das mit static zu tun?
Das alles (auch ein paar typische stilistische Anfängerfehler in deinem Beispiel) klingt sehr danach, als würdest du mit Sprachmitteln herumspielen, die du selber nicht verstehst. Kein Wunder, dass da solche Fehler bei auftreten. Ich wäre zum Beispiel auch nicht sicher, ob puts threadsicher ist.
-
voidpointer schrieb:
Die statischen Arrays sind auf jeden Fall pro Thread!
Absoluter Unsinn am Sonntagmorgen.
Du willst zeitkritischen Code mit lokalem static behandeln?
Das ist ebenso Unsinn, ein lokales static verhindert per se Multithreadfähigkeit.
-
voidpointer schrieb:
Wieso static? Die Ausgabe ist (wirklich) extrem laufzeitkritisch!
Abgesehen davon, dass dir das static da herzlich wenig hilft, machst du vermutlich irgendetwas falsch, wenn eine Konsolen/GUI-Ausgabe performancekritisch ist.
-
Hi,
ja ich gebe zu es ist C++ mit drin. Und ich gebe zu, dass das mit static falsch war. Aber beenden wir bitte das static-Thema; das static habe ich ja schon herausgenommen.
Aber der Fehler besteht nachwievor (nämlich, dass der int als 0 angezeigt wird).
Hat jemand eine Idee was der Fehler sein könnte?
Danke für jede Hilfe!Gruß,
Johannes
-
voidpointer schrieb:
Aber der Fehler besteht nachwievor (nämlich, dass der int als 0 angezeigt wird).
Hat jemand eine Idee was der Fehler sein könnte?
Danke für jede Hilfe!Da du ziemlich hilflos mit den Threads zu sein scheinst, ist die starke Vermutung, dass du da noch mehr Dummheiten gemacht hast. Aus Versehen oder aus falschverstandenen Optimierungswünschen (static zur Beschleunigung? Wo nimmt man solche Vorstellungen her?). Ohne Code kann man nicht mehr sagen. Schrumpf dein Programm soweit wie möglich zusammen, so dass es gerade noch den Fehler enthält und wir das Problem nachvollziehen können. Außerdem mach Mutexe um deine Ausgabe. Du willst ja sicherlich sowieso nicht, dass wenn zwei Threads "Hallo" und "Welt" schreiben "HaWlellot" rauskommt, also täte das der Ausgabe insgesamt gut. Und mach deine Optimierungsspielereien raus. Du scheinst da irgendwelche eigenen komischen Vorstellungen entwickelt zu haben oder hast eine gaaaannnz schlechte Quelle. static optimiert nichts sondern sagt was über Sichtbarkeit und Speicherbereiche. const ist keine Optimierung sondern ein Schutz vor eigenen Fehlern, unnötige consts an Stellen wo sie keine Fehler verhindern können, deuten da drauf hin, dass dir dies nicht klar ist. Vermutlich hast du daher noch mehr solche Hauer drin.
Und auch in C++ sind Threads keine richtigen Objekte. (Eigentlich in keiner Sprache die ich kenne)
-
Hi,
ich kenne const und so schlimmer Optimierungsfreak bin ich jetzt auch nicht. Ich finde es nur sauberer.
Zum Problem: Es war nichts mit Threads. Hier ist der Fehler:
out("long long int: %ldd, int: %d", longLongIntVar, intVar);
schlägt fehl, die 2te Variable ist 0. Richtig ist:
out("long long int: %lld, int: %d", longLongIntVar, intVar);
Das funktioniert dann auch
Wohl ein Speicherzugriffsfehler.
Abschließende Frage (wenn vllt auch nicht ANSI): Kann ich meinem Compiler (g++ 4.6) sagen, dass er einen formatString-Check machen soll? Damit sowas nie wieder passiert...
-
voidpointer schrieb:
Zum Problem: Es war nichts mit Threads.
Keine Sorge, das kommt noch, zumindest solange du dich nicht mal ein bisschen damit beschäftigst.
voidpointer schrieb:
Hier ist der Fehler:
Deswegen kopiert man nach Möglichkeit auch seinen Code, und postet nicht einfach irgendetwas.
voidpointer schrieb:
Damit sowas nie wieder passiert...
Wenn du eh C++ benutzt, wie wäre es dann mit einem sauberem operator << ?
-
cooky451 schrieb:
Wenn du eh C++ benutzt, wie wäre es dann mit einem sauberem operator << ?
Seine Anwendung ist doch performancekritisch. Dass C++ Streams total lahm sind, weiß doch jeder!
-
voidpointer schrieb:
Abschließende Frage (wenn vllt auch nicht ANSI): Kann ich meinem Compiler (g++ 4.6) sagen, dass er einen formatString-Check machen soll? Damit sowas nie wieder passiert...
Jain. Mit den Warnoptionen wird das schon gemacht, das funktioniert aber nur, wenn du den Formatstring direkt in der ausgabeanweisung stehen hast, nicht wenn der über drei Ecken an diese weitergereicht wird.
cooky451 schrieb:
voidpointer schrieb:
Hier ist der Fehler:
Deswegen kopiert man nach Möglichkeit auch seinen Code, und postet nicht einfach irgendetwas.
+1. Das hätten wir dir gleich sagen können, wenn du es nur gezeigt hättest.
Immerhin hast du so noch einen anderen, gefährlicheren Fehler gezeigt bekommen.
-
Naja der Grund, nicht cout zu Benutzen war nicht die Performance. Sicher eine interessante Frage, aber mein Problem ist, dass solche Sachen wie
cout << einStringMitBackslashN;
noch atomar auf meiner Konsole aussehen, aber
cout << einString << einInt << nochEinString;
manchmal durcheinander gewürfelt werden (zwischen den << Ops). Daher dachte ich, zuerst vsprintf und dann an cout.
-
Da passt als Antwort nur:
cooky451 schrieb:
voidpointer schrieb:
Zum Problem: Es war nichts mit Threads.
Keine Sorge, das kommt noch, zumindest solange du dich nicht mal ein bisschen damit beschäftigst.
Da haben wir's.
Und vorhin war's noch so extrem kritisch, dass du irgendwelche static-Tricks bei der Ausgabe machen wolltest (noch dazu über einen scheinbar unnötigen Umweg
) und nun ist es halb so wild?
-
voidpointer schrieb:
Daher dachte ich, zuerst vsprintf und dann an cout.
vsprintf funktioniert auch nur, weil du Glück hast. Du musst in jedem Fall irgendeinen threadsicheren Wrapper bauen. Bei operator << könntest du dann z.B. gesondert auf flush reagieren.
Aber um das noch mal zu betonen: Performancekritische Ausgabe auf der Konsole? Du machst etwas falsch! Die Ausgabe auf der Konsole ist so unglaublich langsam, wenn das performancekritisch ist, ist dein Programm wahrscheinlich 99% der Zeit am warten.
Was schreibst du denn da alles rein?
-
voidpointer schrieb:
Abschließende Frage (wenn vllt auch nicht ANSI): Kann ich meinem Compiler (g++ 4.6) sagen, dass er einen formatString-Check machen soll? Damit sowas nie wieder passiert...
Aktuelle gcc warnen hierbei, so wie gewünscht.
Beim C++ "<<" natürlicherweise nicht ebenso häufig.