C++11 std::cout不打印数字的奇怪行为

C++11 std::cout不打印数字的奇怪行为,c++11,cout,thread-local-storage,C++11,Cout,Thread Local Storage,以下代码(作为大型项目的一部分编译)不打印数字(不仅仅是数字,还有任何数字:std::int32_t,std::size_t,double,等等)。当然,这段自行编译的代码工作得非常完美,因此不可能提供一个再现此问题的最小示例:这个大项目中的某些内容导致了此问题的发生,但我无法确定到底是什么原因导致了此问题 守则: std::int32_t n = 42; std::cout << "test 1" << std::endl; // prints std::cout &l

以下代码(作为大型项目的一部分编译)不打印数字(不仅仅是数字,还有任何数字:
std::int32_t
std::size_t
double
,等等)。当然,这段自行编译的代码工作得非常完美,因此不可能提供一个再现此问题的最小示例:这个大项目中的某些内容导致了此问题的发生,但我无法确定到底是什么原因导致了此问题

守则:

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
因此,数字文本
3.14
456464
以及变量
n
以及字符串
测试2
(我尝试在整数打印失败后打印字符串)。
printf
功能起作用。我使用
std::endl
,因此它不应该是任何类型的缓冲问题

使用
std::cout.clear()
似乎可以解决问题(我们可以再次打印字符串),但只能在打印另一个数字之前

什么样的输出流操作可能会导致这种情况?是的,有
使用名称空间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
链接命令行:

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
g++-o可执行文件-s\\
-Wl,--buildid=uuid-static libstdc++-pthread-Wl,--no未定义

经过一些调试,我终于找到了罪魁祸首。这不是一个完整的答案,因为它没有解释观察到的症状(没有特别打印数字以及为什么使用
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
现在使用Python和
ctypes
模块加载我们的库:

import numpy as np
lib = np.ctypeslib.load_library('libtest', '.')
lib.fun()
如果这样运行,它将打印(如预期的那样):

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

g++ -std=c++11 -fPIC test.cpp -s -static-libstdc++ -pthread -shared -o libtest.so
import numpy as np
import cv2  # <-----
lib = np.ctypeslib.load_library('libtest', '.')
lib.fun()

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

经过一些调试,我找到了罪魁祸首。这不是一个完整的答案,因为它没有解释观察到的症状(没有特别打印数字以及为什么使用
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
现在使用Python和
ctypes
模块加载我们的库:

import numpy as np
lib = np.ctypeslib.load_library('libtest', '.')
lib.fun()
如果这样运行,它将打印(如预期的那样):

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

g++ -std=c++11 -fPIC test.cpp -s -static-libstdc++ -pthread -shared -o libtest.so
import numpy as np
import cv2  # <-----
lib = np.ctypeslib.load_library('libtest', '.')
lib.fun()

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

这将很难复制。如果有可能创建一个复制问题的,请包括一个适当和完整的文档,以向我们展示。另外,请向我们展示您用于构建失败程序的确切命令。正如我提到的,如果我知道项目的哪一部分导致了问题,我不会问这个问题。代码库是巨大的,共享它是不可行的。我将添加我使用的编译器和链接器标志的问题。如果使用版本控制系统,请逐个提交,直到问题不再存在。然后你可以做一个比较,看看是什么导致了它。如果你没有一个版本控制系统,那么通过注释最近的代码来进行回溯,直到它工作为止。这就是设置的失败位
printf
std::cout
没有直接关系(据我所知,这样做很好。在调用
std::cout.clear()之后
,又好了。这表明出现了一个故障位。至于是什么导致了故障位,我不知道。您的代码似乎很好,所以可能只是没有足够的上下文或其他内容。您是否对
std::cout
做了什么特别的处理?恐怕我要结束了。您似乎无法重现这一点t更多的上下文。这将很难复制。如果有可能创建一个复制问题的上下文,请包含一个适当的完整的上下文来向我们展示。另外,请向我们展示确切的命令你用来构建失败的程序。正如我所提到的,如果我知道项目的哪一部分导致了问题,我就不会问这个问题。代码库很大,无法共享。我会在问题中添加我使用的编译器和链接器标志。如果你使用版本控制系统,然后逐个提交,直到问题解决为止如果你没有版本控制系统,那么通过注释最近的代码直到它工作。这就是设置的失败位。
printf
std::cout
没有直接关系(据我所知,一切正常。在调用
std::cout.clear();
之后,一切又正常了。这表明出现了一个故障位。至于是什么导致了故障位,我不知道。您的代码似乎正常,所以可能只是没有足够的上下文或其他内容。您对
std::c做了什么特别的事情吗