printf modifizieren und stdout capturn

M

mythos

Mitglied
Hallo,

ich moechte das Verhalten aller *printf Funkionen modifizieren und zwar sollen diese statt auf stdout in char strings schreiben. Mit anderen Worten, ich will stdout capturn und in einem char* speichern.

Mir ist klar, dass das Anliegen ein wenig sonderbar klingt. Stdout soll insbesondere nicht mit freopen in ein File umgeleitet und aus dem File wieder eingelesen werden. Ich verwende ein Testtool; sobald die Daten in Files geschrieben und wieder gelesen werden, verlassen sie den Scope ueber den das Testtool effektiv nachdenken kann.

Die Fragen sind nun:
a.) Gibt's einen besseren Weg mein Vorhaben anzugehen?
b.) Ich will nicht alle *printf Funktionen neu schreiben muessen bzw. das Implementieren des Formatstring-Handling stell' ich mir recht unlustig vor. Existiert eine Art printf-Kernfunktion, die ich ersetzen kann, die Auswirkungen auf alle anderen hat? Welche?

mythos
 
ich moechte das Verhalten aller *printf Funkionen modifizieren und zwar sollen diese statt auf stdout in char strings schreiben.
Nicht alle *printf Funktionen schreiben auf stdout. Kennst du snprintf?

Weitere Frage: ist pipe() eine Möglichkeit?

b.) Ich will nicht alle *printf Funktionen neu schreiben muessen bzw. das Implementieren des Formatstring-Handling stell' ich mir recht unlustig vor. Existiert eine Art printf-Kernfunktion, die ich ersetzen kann, die Auswirkungen auf alle anderen hat? Welche?
Ich würde dir sehr stark von diesem Vorhaben abraten (C Standard-Bibliothek um-/neuschreiben..).
 
Hallo,

Danke fuer deine Antwort.

Nicht alle *printf Funktionen schreiben auf stdout. Kennst du snprintf?

Klar. Fuer's erste reicht mir stdout.

Weitere Frage: ist pipe() eine Möglichkeit?

In der Tat. Das ist eine gute Idee. Ich muss das ausprobieren und melde mich wieder wenn es funktioniert bzw. nicht funktioniert.

Ich würde dir sehr stark von diesem Vorhaben abraten (C Standard-Bibliothek um-/neuschreiben..).

Auch das ist klar. Jeder vernuenftige Mensch wuerde das vermeiden wollen. Ich seh nur keine andere Moeglichkeit. Auf der anderen Seite ist ein Testsystem, das mit einer eigenen Dummy-Variante der Standard-Bibliothek arbeitet, nichts ungewoehnliches.

mythos
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Hallo,

Funktioniert zwar ohne Testtool, aber nicht mit.

mythos
 
Zuletzt bearbeitet:
Funktioniert zwar ohne Testtool, aber nicht mit.
Ok, was "funktioniert", was hast du gemacht? Was "funktioniert nicht", kannst du ein Testprogramm mit Angabe von "was soll passieren" und "was passiert tatsächlich" angeben, vielleicht werden dann ja ein paar Sachen klarer (zumdindest für mich).

Ich hab generell ein paar Probleme wenn ich dein ursprünglichen Post durchlese: wie genau soll in ein char Array geschrieben werden, weißt du im vornherein wieviel Output generiert werden wird? Oder soll der "stdout-string" dynamisch vergrößert werden?

mythos schrieb:
ar0 schrieb:
Nicht alle *printf Funktionen schreiben auf stdout. Kennst du snprintf?
Klar. Fuer's erste reicht mir stdout.
Das versteh ich nicht. Wie meinst du das, fürs erste reicht dir stdout?
snprintf schreibt ja bereits in ein char Array. Dann müsstest du nur noch die Aufrufe von printf durch snprintf in deiner Anwendung "Austauschen" (und natürlich den Overhead für das string-management hinzufügen).
Aber hier stellt sich natürlich auch die Frage, ob du überhaupt die Möglichkeit hast die printf-Aufrufe im Quelltext zu verändern oder ob du einfach nur "von außen" auf stdout des Prozesses zugreifen kannst.

Naja, das (ursprüngliche Vorhaben) klingt für mich nach ziemlicher hack-Arbeit, da müsstest du wahrscheinlich bei den Codern die hinter der Implementierung deiner C-Standard-Lib stehen (glibc, BSD libc, ...?) nachfragen.

Ich würd mal schätzen wenn du auf etwas unixoidem unterwegs bist ist comp.unix.programmer ein guter Anlaufpunkt, auch wenn du dort wahrscheinlich nur weiterführende Links und/oder hilfreiche Belehrungen ala "Lass es" bekommst (ehehe). Aber wie ich das mitbekommen hab laufen dort Leute mit Ahnung rum.
 
Ich glaub, du stellst dir das falsch vor. Ich versuche ein bisschen besser zu beschreiben, woran ich eigentlich arbeite. (Die Antwort passt zwar nicht umbedingt auf deine Fragen, aber ...)

Immer, wenn ich Testtool schreibe, meine ich sowas wie einen selbstgeschriebenen C-Compiler, der zwar keinen Code produziert, aber einiges an Analyse-Arbeit leistet. Nun moechte ich Support zur Analyse/zum Aufzeichnen von stdout, stderr, etc. schaffen und in den Compiler integrieren. Die einfachste Methode Aenderungen am Compiler vorzunehmen ist es Aenderungen _nicht_ am Compiler selbst vorzunehmen, sondern in der libc oder in den Testdrivern. Testdriver ist eine main() Funktion, die bestehenden (zu testenden) Programmcode exemplarisch aufruft.

Fuer's erste wollte ich versuchen nur stdout aufzuzeichnen. Wenn jemand auf stderr oder in ein File schreibt, ist mir das egal. Am Code under Test soll nichts veraendert werden. Ich kann also nicht hergehen und alle printfs im Programm gegen sprintfs ersetzten. Die Idee war, sich vor die Standardlib reinzuhacken, in pseudo-code:

// mein printf(.)
int printf(.) {
//speichere alles was auf printf rausgeht in einem riesigen buffer, der sich selbst dynamisch vergroessert
// ruf das echte printf auf und tu su als waere nicht's gewesen
return printf(.)
}

Und das fuer alle Funktionen die auf stdout schreiben koennen. Bei fprintf ist das ein bisschen komplizierter, etc etc.

Die pipe-Idee war zwar im Prinzip recht cool. Mein Compiler kann das aber nicht richtig verarbeiten.

Im Grunde funktioniert es auch Funktionen von der Standardlib zu ersetzen oder neu zu schreiben, aber im Moment implementiere ich Zweit-Version der Funktion mit prefix "my_".

Funktioniert es auch, wenn beide Funktionen gleich heissen. Im besten Fall sollte das Interface nach auszen gleich bleiben. (Andernfalls kann ich automatisiert zwar alle printf(.) gegen my_printf(.) mit einem Preprocessing-Schritt ersetzen lassen; lieber waer's mir, wenn ich das einsparen koennte.) Wie bring ich (zum Beispiel dem gcc) bei, dass ich eine eigene Versionen von printf habe und gleichzeitig das echte printf verwenden moechte? Kann ich aus Libs nur teilweise inkludieren? (z.B.: Ich hab' mein eigenes standalone printf geschrieben. Wie bring ich dem gcc bei, dass ich den Prototypen von printf nicht brauche, aber den Rest von stdio.h schon? Wie bring ich gcc bei, dass ich nur printf von der standardlib nicht linken will?)
 
Ist dein Applikation dynamisch gelinkt? Wenn ja kannst du den dynamic linker dazu zwingen eine ander Bibliothek vor der libc zu laden. Diese andere Bibliothek kann dann eine eigene Implementierung der printf Funktion beinhalten. Der Vorteil ist dass du weder in den eigentlichen Code, noch in den Kompelierprozess eingreifen musst.

Beispiel:
main.c:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
printf("Hallo World!\n");
printf("Hallo Du");

return 0;
}


mylib.c:

#include <stdio.h>

int printf(const char *format, ...)
{
fprintf(stdout, "Aufruf meiner privaten printf Funktion!\n");
return 0;
}

int puts(const char *s)
{
fprintf(stdout, "Aufruf meiner privaten puts Funktion!\n");
return 1;
}


Übersetzen:
gcc -Wall -o main main.c
gcc -shared -Wall -o libmy.so mylib.c

Beim Aufruf wird der dynamic linker nun dazu gezwungen die Library libmy.so vor der libc zu laden:

# LD_LIBRARY_PATH=/home/rainer/unixboard/preload LD_PRELOAD="libmy.so" ./main
Aufruf meiner privaten puts Funktion!
Aufruf meiner privaten printf Funktion!
#


Anscheinend wird irgendwo beim Übersetzten von main.c erkannt, dass beim ersten Aufruf von printf ein Newline verwendet wird und daher wird intern die puts Funktion verwendet.

Hoffe das hilft!

LG,
Faxe
 
Zurück
Oben