标准 C++ 线程 ID - 奇怪的行为
Posted
技术标签:
【中文标题】标准 C++ 线程 ID - 奇怪的行为【英文标题】:Standard C++ Thread IDs - strange behavior 【发布时间】:2013-06-03 14:06:50 【问题描述】:我需要按需创建一些线程,因为我之前不知道我需要多少。
使用向量std::vector<std::thread> threads;
“存储”线程即时消息
每次我创建一个新线程时,我都会将它们推回到向量上:threads.push_back(std::thread(worker));
为了存储(用于测试)线程 ID,我使用以下代码:double test = std::hash<std::thread::id>()(std::this_thread::get_id());
根据 cpp-references hash、thread::id 和 get_id 这应该可以正常工作。
但只有这一行我得到的 id 总是 0(零)
如果 id 在散列线下方添加以下行,它可以工作,我从线程中得到一个散列 id:std::thread::id tid = std::this_thread::get_id();
即使我不使用tid
有人可以解释这种行为吗? 我正在使用eclipse juno并多次清理+重建项目......我只是不明白:/
这里是代码: (一行一行,因为这里的格式规则很愚蠢-.-
std::vector<std::thread> threads;
void worker ()
double test = std::hash<std::thread::id>()(std::this_thread::get_id());
std::thread::id tid = std::this_thread::get_id();
printf("%ld\n", test);
void joinThreads(std::thread& t)
t.join();
int main()
for (int i = 0; i < 10; ++i)
threads.push_back(std::thread(worker) );
std::for_each(threads.begin(),threads.end(),joinThreads);
return 0;
【问题讨论】:
已添加代码.. 花了一段时间,因为我总是收到“错误”格式 Oo 的错误 【参考方案1】:在 x86_64 上,printf
的 double
参数将在不同的寄存器中传递给 long
参数,因此当您调用 printf("%ld\n", test)
时,编译器会将 test
放入浮点寄存器并调用函数.然后printf
实现在非浮点寄存器中查找参数,因为"%ld"
转换说明符告诉它期待long int
参数。因为实际参数与printf
查找的寄存器不在同一个寄存器中,所以找不到值。
当您添加下一行时,它会导致 tid
的值位于非浮点寄存器中,显然这允许 printf
找到它(但不要依赖它,它是未定义的行为和不可预测。)
解决方案:如果您不能正确使用printf
,则根本不要使用它。要么使用为 double
指定的正确转换,即 "%f"
,要么将值存储在不同的类型中,或者使用 iostreams。
【讨论】:
+1 很好地解释了可能导致观察到的行为的原因。【参考方案2】:格式说明符不正确,因为%ld
是long
,而不是double
,因此程序具有未定义的行为。另外,std::hash<>::operator()
的返回值类型是size_t
,而不是double
。请改用(类型安全)std::cout
:
auto test = std::hash<std::thread::id>()(std::this_thread::get_id());
std::cout << test << std::endl;
【讨论】:
【参考方案3】:你的输出是错误的。 %d
不是double
,它代表十进制,即int
s。
你想要的是
printf("%f\n", test);
当然,如果您首先使用 std::cout
,这一切都不会发生,正如 hmjd 的回答所建议的那样。
【讨论】:
%ld 实际上是我想要的。在 gdb 中,输出是[New Thread 0x7ffff308f700 (LWP 20234)]
十六进制值是 id。如果我用 %f 打印它,它的值不一样吗?还是我只是困惑?
那么为什么首先将哈希保存为双精度值?本来可以留一个size_t
,这是std::hash
的原始返回类型。
@baam,你很困惑。如果你将double
传递给printf
,你必须告诉它你传递了一个双倍,使用"%f"
...如果那不是“实际上你想要的”(或认为你想要的)真的没关系) 因为你做错了会导致未定义的行为。如果你想要一个十六进制值,那么你不想要"%ld"
或 "%f"
,因为它们都不打印十六进制值!如果你不能正确使用printf
,那就不要使用它。
嗯.. 我可以发誓我以前用过 size_t,我也得到了一个零。但它现在工作正常.. 谢谢:)以上是关于标准 C++ 线程 ID - 奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章