Sådan frigøres () både stdout og stderr til en enkelt outputfil under Windows

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har en Windows Win32/GUI-applikation, der undertiden udskriver interessant output til både stdout og stderr, så det jeg gerne vil gøre er at fange den output til en fil til revision efter ansøgningen har forlades.


Problemet er, jeg kan med held kalde freopen\_s() for at fange stdout output til en fil, eller Jeg kan bruge den til at fange stderr output til en fil, men forsøger at gøre begge på én gang giver kun en afkortet fil med munged data.


Nedenfor er et simpelt program, der gengiver problemet; hvis jeg kommenterer en af ​​de to freopen\_s() opkald, så får jeg den forventede udgang i den blah.txt fil, der oprettes (dvs. en af ​​de to tekstlinjer), men hvad jeg synes er at ende med en blah.txt, der indeholder begge tekstlinjer.


Er det muligt under Windows? Jeg kunne falde tilbage til at oprette to forskellige filer (fx blah\_stdout.txt og blah\_stderr.txt), men jeg vil hellere ikke, siden da skal jeg manuelt rekonstruere den relative rækkefølge, hvor stdout og stderr output blev genereret .


int main(int argc, char *argv[])
{
   const char * outFileName = "blah.txt";
   FILE * junk1 = NULL, junk2 = NULL;
   if (freopen\_s(&junk1, outFileName, "w", stdout) != 0) abort();
   if (freopen\_s(&junk2, outFileName , "w", stderr) != 0) abort();
   printf("This text was printed to stdout and should appear in blah.txt
");
   fprintf(stderr, "This text was printed to stderr and should appear in blah.txt
");
   return 0;
}

Bedste reference


'W' åben tilstand er dokumenteret som



  Åbner en tom fil til skrivning. Hvis den givne fil eksisterer, ødelægges indholdet.



men selv 'w +' og 'a' fejler.


Hvis du bruger en CRT, der har dup2, kan du gøre dette:


#include <io.h> // MS CRT

...

FILE * junk1 = NULL;
if (freopen\_s(&junk1, outFileName, "w", stdout) != 0) abort();
\_dup2(1, 2); // Assign stderr to same file as stdout


Denne kode skrev begge linjer til filen, da jeg testede det, men det fremgår af bemærkningerne, at dette måske ikke altid er tilfældet. Ældre versioner af Visual Studio er mere tilbøjelige til at arbejde.


Hvis du er villig til at smide alle portabiliteter ud, kan du også få adgang til strukturen bag FILE-objekterne (struct \_iobuf) (\_iob/\_\_iob\_func) og overskrive medlemmerne med værdierne fra den anden fil. Dette er ikke muligt i VS 2015 og senere: [16]



  FIL Encapsulation: I tidligere versioner var FIL-typen helt defineret i < stdio.h > ;, så det var muligt for brugerkode at komme ind i en FILE og muck med sine internals. Vi har refactored stdio biblioteket for at forbedre indkapslingen af ​​detaljer om bibliotekets implementering. Som en del af dette er FIL som defineret i nu en ugjennomsigtig type, og dens medlemmer er utilgængelige uden for CRT selv.