std :: cout的奇怪行为无法显示数字

时间:2019-07-10 11:11:03

标签: c++11 cout thread-local-storage

以下代码(作为大型项目的一部分进行编译)不会打印数字(不仅是one-byte integers,而且还包括以下任何一个:std::int32_tstd::size_tdouble等)。当然,此代码本身可以完美地编译,因此不可能提供一个最小的示例来重现此问题:这个大项目中的某件事导致了它的发生,但我无法完全理解导致它的原因。 -因此是这个问题。

代码:

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

输出:

test 1
printf: 1
test 3

因此,数字文字3.14456464以及变量n的输出不如字符串test 2(我在整数打印失败后尝试打印字符串) )。 printf函数起作用。我使用std::endl,所以它应该不是任何缓冲问题。

使用std::cout.clear()似乎可以解决问题(我们可以再次打印字符串),但是只能等到另一个数字被打印出来。

对输出流进行哪种操作可能会导致这种情况?是的,有using namespace std;

使用GCC工具链用-std=c++11编译代码(我尝试了5.3.1、6.3.1和8.2.0的各种版本-结果始终相同)。

编译命令行:

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

链接命令行:

g++ <object files> -o executable -s \\
-Wl,--build-id=uuid -static-libstdc++ -pthread -Wl,--no-undefined

1 个答案:

答案 0 :(得分:0)

经过一些调试后,我设法找到了罪魁祸首。这不是一个完整的答案,因为它不能解释观察到的症状(不是特别打印数字,以及为什么使用std::cout.clear()至少可以部分解决问题),但是此答案将提供一个最小的示例,可以用来重现问题。希望它将为某人节省一些时间。

出现异常行为的原因是内存使用问题,即线程本地存储(TLS)用完了。可以通过涉及大量使用TLS的任何方式来重现该问题。下面的示例使用OpenCV并为此静态链接到libstdc++。为了加快速度,我们将使用Python避免编写过多的代码。

C ++部分:

#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

编译并与之链接(-static-libstdc++在此很重要,因为该库因大量使用TLS而闻名)

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

现在使用Python和ctypes模块加载我们的库:

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

如果这样运行,它将打印(按预期):

hello 0
42
hello 1

现在让我们添加另一个大量使用TLS的库:

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

这将打印:

hello 0

请注意,特定的可重复性可能取决于您操作系统的TLS限制设置。