0

I have this strange problem with stdout/stderr.

I want to apologize for not being able to put here the original code, it's too long / too many libraries dependent etc...
So please let me know if you ever encountered anything like it, or what may cause this issue without getting the original code, only the idea and examples of the simple things I tried to do:

  • I'm using g++ (GCC) 4.4.6 20120305 (Red Hat 4.4.6-4) on RHEL 6.3
  • I couldn't isolate the problem for putting it here, I'll give code examples of what I did.
  • fprintf() / printf() / std::cout stops working after a while. I'm using boost::asio::io_service with deadline_timer in order to call a my_print() function.
    This my_print() function prints to screen every 1 second some information.

In order to print, I use alignments, like the following:

fprintf(stdout, "%*s\n", -printWidth, someEnumToStr[i]);
fprintf(stdout, "%s\n", aString);
fprintf(stdout, "%u\n", num);

While aString is a std::string. Sometimes I construct aString from std::ostringstream.
Sometimes I construct it with snprintf().

  • I have an std::map with information, exactly 16 elements inside the map. I iterate over it, and for each element I try to print data with the example of fprintf() above.
  • For an unknown reason, the line of element 16 isn't printed.
  • If I call the executable, and redirect stdout to a file (./a.out > aaa.txt) the line of element 16 is getting printed.
  • If I open a new FILE* and fprintf() to this file, again, everything is getting printed (all lines, including line of element 16)
  • Before using fprintf() I tried to use std::cout (and alignments with std::cout.width(printWidth) << std::left...), The same behavior happened, but when line 16 wasn't drawn, stdout got stuck (I mean, the program still worked, but nothing was printed to stdout never again. I had to call std::cout.clear() for it to work again). Since a point in the code, which I couldn't lay my hands on, std::cout.failbit and badbit were 1.
  • If I run the code with valgrind this behavior doesn't happen. valgrind doesn't say anything wrong.
  • If I run it with gdb it happens, but gdb doesn't say anything wrong.
  • If I run it in an IDE (clion) in debug mode, it doesn't happen.
  • If I run it in IDE, without debug, it happens.
  • I figure it depends on the printWidth I give for the alignment in fprintf() - When printWidth is bigger, it happens sooner (when it's smaller, line 16 is randomly getting printed).
  • Another important thing: it happens more frequently when there is more to print.
  • I tried to give std::cout a bigger buffer (not his default) and it didn't work.
  • I tried to buffer all of the output into a buffer (instead of printing each line), then to only fprintf() once. Same behavior happens.
  • I didn't find anywhere in the code I try to print a NULL pointer.
  • I print with \n every couple of fprintf()s, and do fflush() in the end of my_print()

Please let me know if you know anything.


Illustration:

deadline_timer..... every 1 sec... my_print()
boost::asio::io_service.run

my_print() {

    for(std::map<>::iterator... begin, end, ++it....) {
        fprintf()s....
    }
}
hudac
  • 2,584
  • 6
  • 34
  • 57
  • 2
    You should probably make a [SSCCE](http://sscce.org). – zneak Sep 10 '15 at 18:11
  • I can but it will be pointless – hudac Sep 10 '15 at 18:34
  • At least you should show us all the types. I'd suspect that `printwidth` is some integer type but not an `int`. `va_arg` arguments are very picky about that. Do you compile with `-Wall` ? – Jens Gustedt Sep 10 '15 at 18:38
  • It's an `int`... What other types do you want me to explicitly say? (of course I forgot to say all of the details..) – hudac Sep 10 '15 at 18:40
  • 1
    "I have .. exactly 16 elements inside the map." and `"the line of element 16 isn't printed": Is this an off-by-one and code has element 0, element 1, ... element 15, but no element 16? – chux - Reinstate Monica Sep 10 '15 at 18:55
  • 1
    Since you refuse to post anything that might help, it remains to clutch at straws. The erratic behaviour can be symptomatic of indexing beyond array bounds. You seem to use the phrases "16 elements" and "element 16" as if they are interchangeable, but they are not. As @chux said a few seconds before me. – Weather Vane Sep 10 '15 at 18:56
  • 2
    "the line of element 16 isn't printed." and "If I call the executable, and redirect stdout to a file ... the line of element 16 is getting printed." Then how do you know line of element 16 is not printed versus it being _overprinted_ by following text? A hexdump of the re-directed output may show a CR without LF. – chux - Reinstate Monica Sep 10 '15 at 18:59
  • I have elements: 1 till 16 includes. (16 elements total). If there's out of.bound issues, why does'nt valgrind say anything? – hudac Sep 10 '15 at 19:03
  • I print to stdout and a file concurrently, the file got the corrent printout abd the stdout.not – hudac Sep 10 '15 at 19:08
  • "I have elements: 1 till 16 includes" is that how you index them? Or do you index them 0 till 15? – Weather Vane Sep 10 '15 at 19:10
  • "I print to stdout and a file concurrently". Does that mean to one and then to the other? Doing one may cause the damage that makes the other malfunction. – Weather Vane Sep 10 '15 at 19:14
  • 1
    @hudac - Sorry to press, but how did you conclude "the stdout.not"? How does looking at output detect overprinted text? – chux - Reinstate Monica Sep 10 '15 at 19:17
  • I'll try to dump the buffer with hex to see if there's any special characters, or any CR without LF. I have an `std::map` that have elements, which they key is 1 till 16, I iterate over them so I iterate on the correct map elements. When iterating, `map.size()` is 16 (and `stdout` prints 15 lines). When I print to `stdout` and to a file, I print the same buffer. why does it matter if I do `fprintf(myfile, "%s", buff);` and then `fprintf(stdout, "%s", buff);` or the other way around? – hudac Sep 11 '15 at 07:15
  • I looked on the dump in the output to file, there are no special characters... – hudac Sep 11 '15 at 13:17

3 Answers3

1

Non printable characters may be breaking terminal.

fprintf(stdout,"%s", astdstring.cstr() );

Is how to print std::string

mksteve
  • 12,614
  • 3
  • 28
  • 50
  • yes, I print `std::string` with `c_str()`... I'll try to dump the buffer with hex to see if there's any special characters – hudac Sep 11 '15 at 07:09
1

I use boost::asio, I have a callback to read from stdin. this read is nonblocking - happens with async_read_some().
The problem was stdin was turned to be nonblocking, and it also caused stdout to be nonblocking as well because they point to the same file description (explanation).
It caused the fprintf() calls to fail (returned -1 with errno 11) and not all of the output got printed out on the screen.

It has no relation to boost.
I succeeded isolating the problem, the following code creates this problem:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>

using namespace std;

int main(int argc, char *argv[]) {

    const int problem = 8000;
    const int myBuffSize = 32000;
    char *myBuff = new char[myBuffSize];
    int myoffset = 0;
    memset(myBuff, '-', myBuffSize);
    int flags;

    bool toogle = true;
    bool running = true;

    // Comment from here
    if ((flags = fcntl(STDIN_FILENO, F_GETFL, 0)) < 0) {

        printf("error fcntl()\n");
        return 0;
    }
    if (fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK) < 0) {
        printf("error fcntl()\n");
        return 0;
    }
    // Comment until here

    while(running) {

        toogle = toogle ? false : true;
        if (toogle) {

            snprintf(myBuff + problem, myBuffSize - problem, "fin\n\n");
        } else {
            snprintf(myBuff + problem, myBuffSize - problem, "end\n\n");
        }
        fprintf(stdout, "%s", myBuff);
        sleep(1);
    }

    delete[] myBuff;
    return 0;
}

If you'll comment the // Comment from here to // Comment untill here, it will print all of the output (fin and end will be printed).

One solution to this problem is to open another fd to the current tty using fopen(ttyname(STDOUT_FILENO), "w") and to print into it.
I believe another solution is to async_write() into screen.

Community
  • 1
  • 1
hudac
  • 2,584
  • 6
  • 34
  • 57
  • Absolutely brilliant! You just saved me a LOT of time (already wasted a whole day on this but didn't get any closer). I had the exact same behavior of erratic failures to std::cerr (or std::cout). After reading your answer I checked if I accidently had set fd 0, 1 and/or 2 to non-blocking and indeed! Thank you for the question and adding your solution! – Carlo Wood May 13 '19 at 03:26
0

The output might be stuck in a buffer, and not flushed before program termination.

Try adding exit(0) at the end of the program, and see if it helps.

http://www.cplusplus.com/reference/cstdlib/exit/

All C streams (open with functions in <cstdio>) are closed (and flushed, if buffered), and all files created with tmpfile are removed.

mrflash818
  • 930
  • 13
  • 24
  • 1
    The output isn't stuck. the next time `my_print()` is being called, there's a new output on the screen, but again, without `line 16`... – hudac Sep 10 '15 at 18:22