1

The following code (compiled as part of a big project) does not print numbers (not just one-byte integers, but any of them: std::int32_t, std::size_t, double, etc). Of course, this code compiled on its own works perfectly, and therefore it is impossible to provide a minimal example which reproduces this problem: something in this big project causes it to happen, but I can't put my finger on what exactly causes it - hence this question.

The code:

std::int32_t n = 42;
std::cout << "test 1" << std::endl; // prints
std::cout << 3.14 << std::endl;     // doesn't print
std::cout << 456464 << std::endl;   // doesn't print
std::cout << n << std::endl;        // doesn't print
std::cout << "test 2" << std::endl; // still doesn't print
printf("printf: %d\n", n);          // prints
std::cout.clear();
std::cout << "test 3" << std::endl; // prints
std::cout << 42 << std::endl;       // doesn't print

Output:

test 1
printf: 1
test 3

So, number literals 3.14 and 456464 and variable n are not printed as well as string test 2 (I attempt to print a string after failed printing of an integer). The printf function works. I use std::endl so it should not be any kind of buffering problem.

Using std::cout.clear() seems to fix the problem (we can print strings again), but only until another number is printed.

What kind of manipulation with output streams may potentially cause this? Yes there is using namespace std;.

The code is compiled with -std=c++11 using GCC toolchains (I tried various versions including 5.3.1, 6.3.1, and 8.2.0 - the result is always the same).

Compilation command line:

g++ c -MMD -pipe -std=c++11 -fPIC -O3 \\
-fmax-errors=3 -msse4.1 -mavx2 source.cpp -o target/objects/source.o

Linking command line:

g++ <object files> -o executable -s \\
-Wl,--build-id=uuid -static-libstdc++ -pthread -Wl,--no-undefined
scrutari
  • 1,378
  • 2
  • 17
  • 33
  • This is going to be very hard to replicate. Please include a proper and full [mcve] to show us, if it's possible to create one that replicates the problem. Also please show us the exact command(s) you use to build the failing program. – Some programmer dude Jul 10 '19 at 11:15
  • As I mentioned, if I knew what bit of the project causes the issue, I wouldn't be asking the question. The code base is huge and it's not feasible to share it. I'll add to the question the compiler and linker flags I use. – scrutari Jul 10 '19 at 11:26
  • If you use a versioning system, then go back commit by commit until the problem doesn't exist anymore. Then you can do a diff to see what might have caused it. If you don't have a versioning system, then do the back-walking by commenting out recent code until it works. – Some programmer dude Jul 10 '19 at 11:30
  • That's the fail-bit getting set. `printf` has nothing to do with `std::cout` directly (as far as I'm aware, so it's fine. And, after you call `std::cout.clear();`, it's fine again. Very indicative of a fail bit. As to what's causing the fail-bit, I don't know. Your code seems fine, so maybe there's just not enough context or something. Are you doing anything special to `std::cout` before hand? –  Jul 10 '19 at 18:16
  • I'm afraid I'm going to flag for closure. There just seems to be no way to reproduce this without more context. –  Jul 10 '19 at 18:34
  • @Chipster, my original hypothesis was that something is happening to std::cout before, but I wasn't able to find anything suspicious, but due to large size of codebase I suspected I could miss something. – scrutari Jul 10 '19 at 18:56

1 Answers1

0

After some debugging I managed to find the culprit. This is not a complete answer because it doesn't explain the observed symptoms (not printing particularly numbers and why using std::cout.clear() solves problem at least partially), but this answer will provide a minimal example that can be used to reproduce the problem. Hopefully it will save some time for someone.

The reason for strange behaviour is problem with memory usage, namely with running out of thread local storage (TLS). The issue can be reproduced in any way which involves heavy usage of TLS. The example below uses OpenCV and linking statically to libstdc++ for this. To speed up things we will use Python to avoid writing too much code.

C++ part:

#include <iostream>
#pragma GCC visibility push(default)
extern "C" void fun() {
    std::cout << "hello 0" << std::endl;
    std::cout << 42 << std::endl;
    std::cout << "hello 2" << std::endl;
}
#pragma GCC visibility pop

Compile and link it with (the -static-libstdc++ is important bit here as this library is known for heavy usage of TLS):

g++ -std=c++11 -fPIC test.cpp -s -static-libstdc++ -pthread -shared -o libtest.so

Now use Python and ctypes module to load our library:

import numpy as np
lib = np.ctypeslib.load_library('libtest', '.')
lib.fun()

If run like this, it will print (as expected):

hello 0
42
hello 1

Now let's add another library with heavy usage of TLS:

import numpy as np
import cv2  # <-----
lib = np.ctypeslib.load_library('libtest', '.')
lib.fun()

This will print:

hello 0

Please note that particular reproducibility may depend on your OS's settings for TLS limits.

scrutari
  • 1,378
  • 2
  • 17
  • 33
  • I'm not sure how this answers the question. Seems like it should be more of an edit to your own question. –  Jul 10 '19 at 18:17
  • 1
    @Chipster, it answers to the part about what "may potentially cause this", but as stated above, it's not a complete answer (though if I had that answer, it would be much better than nothing). – scrutari Jul 10 '19 at 18:25
  • I suppose it does, now that you mention it. BTW: see my first comment on the original post for another partial answer. –  Jul 10 '19 at 18:37