标准C ++线程ID - 奇怪的行为

时间:2013-06-03 14:06:51

标签: c++ multithreading c++11 stdthread

我需要按需创建一些线程,因为我之前不知道我需要多少。 使用向量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 hashthread::idget_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;
}

3 个答案:

答案 0 :(得分:5)

在x86_64上,double的{​​{1}}参数将在不同的寄存器中传递给printf参数,因此当您调用long时,编译器会放置printf("%ld\n", test)在浮点寄存器中调用该函数。然后test实现在非浮点寄存器中查找参数,因为printf转换说明符告诉它期望"%ld"参数。因为实际参数与long int查找的寄存器不在同一个寄存器中,所以无法找到该值。

当您添加下一行时,它会使printf的值位于非浮点寄存器中,并且显然允许tid找到它(但不依赖于此,它是未定义的行为且不可预测。)

解决方案:如果您无法正确使用printf,请完全不要使用它。使用为printf指定的正确转化,即double或将值存储在其他类型中,或使用iostream。

答案 1 :(得分:2)

格式说明符不正确,因为%ldlong,而不是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;

答案 2 :(得分:2)

您的输出错误。 %d不适用于double,代表十进制,即int s。

你想要的是

printf("%f\n", test);

当然,如果您首先使用std::cout,那么就不会发生这种情况,正如hmjd的回答所示。