使用 VS2012 RC 时,如果在 main() 退出后调用 std::thread::join() 则会挂起

2023-12-22

如果在 Ubuntu 12.04 上使用 Clang 3.2 或 GCC 4.7 编译,以下示例会成功运行(即不会挂起),但如果使用 VS11 Beta 或 VS2012 RC 编译,则会挂起。

#include <iostream>
#include <string>
#include <thread>
#include "boost/thread/thread.hpp"

void SleepFor(int ms) {
  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}

template<typename T>
class ThreadTest {
 public:
  ThreadTest() : thread_([] { SleepFor(10); }) {}
  ~ThreadTest() {
    std::cout << "About to join\t" << id() << '\n';
    thread_.join();
    std::cout << "Joined\t\t" << id() << '\n';
  }
 private:
  std::string id() const { return typeid(decltype(thread_)).name(); }
  T thread_;
};

int main() {
  static ThreadTest<std::thread> std_test;
  static ThreadTest<boost::thread> boost_test;
//  SleepFor(100);
}

问题似乎是std::thread::join()如果在之后调用它则永远不会返回main已退出。它被阻止在WaitForSingleObject in _Thrd_join在cthread.c 中定义。

取消注释SleepFor(100);在......的最后main允许程序正确退出,就像制作一样std_test非静态。使用boost::thread也回避了这个问题。

所以我想知道我是否在这里调用了未定义的行为(对我来说似乎不太可能),或者我是否应该针对 VS2012 提交错误?


追踪 Fraser 在他的连接错误中的示例代码(https://connect.microsoft.com/VisualStudio/feedback/details/747145 https://web.archive.org/web/20150501080609/https://connect.microsoft.com/VisualStudio/feedback/details/747145) VS2012 RTM 似乎显示了一个相当简单的死锁案例。这可能不是特定于std::thread- 可能_beginthreadex遭受同样的命运。

我在调试器中看到的内容如下:

在主线程上,main()函数完成后,进程清理代码已获取一个名为_EXIT_LOCK1,称为析构函数ThreadTest,并且正在等待(无限期地)第二个线程退出(通过调用join()).

第二个线程的匿名函数已完成,并在线程清理代码中等待获取_EXIT_LOCK1关键部分。不幸的是,由于时间安排(第二个线程的匿名函数的生命周期超过了第二个线程的匿名函数的生命周期)main()函数)主线程已经拥有该临界区。

僵局。

任何可以延长寿命的东西main()这样第二个线程就可以获取_EXIT_LOCK1在主线程之前避免死锁情况。这就是为什么取消注释 sleep inmain()导致干净关闭。

或者,如果您从ThreadTest局部变量,析构函数调用被移到末尾main()函数(而不是在进程清理代码中)然后阻塞,直到第二个线程退出 - 避免死锁情况。

或者你可以添加一个函数ThreadTest那个叫join()并在末尾调用该函数main()- 再次避免了僵局的情况。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 VS2012 RC 时,如果在 main() 退出后调用 std::thread::join() 则会挂起 的相关文章

随机推荐

  • 更改 Django 管理中日期字段的默认小部件

    如何更改 Django ADMIN 中 DateField 实例的默认小部件 我知道如何为 ModelForm 执行此操作 如何更改 ModelForm 中所有 Django 日期字段的默认小部件 https stackoverflow c
  • 从“angularfire2/database”导入 { AngularFireDatabase, FirebaseListObservable };

    我有问题 import AngularFireDatabase FirebaseListObservable from angularfire2 database 我导入了 AngularFireDatabase 但搜索后 Firebase
  • C# 事件为空

    我正在开发一个项目 在该项目中我需要引发和处理自定义事件 我只是简化了一点代码并得到了如下内容 class Car public int Speed get set public delegate void SpeedTooHigh str
  • 如何使用脚本编辑器(Google Docs 插件)删除 google 文档中的空行?

    我正在创建一个 Google Docs 插件 我试图创建的功能之一是减少两个段落之间的空行数量 因此 举例来说 如果我有 2 个段落 它们之间有 5 个空行 空行 我希望该功能将空行数量减少到 1 本质上 我需要一种方法来检测空行 我看过A
  • Android 蓝牙连接安全不安全

    我一直在研究 Android 2 2 的蓝牙 API API 级别 8 HTC Desire 并且有一个应用程序使用以下方式连接到嵌入式蓝牙设备 device createRfcommSocketToServiceRecord DEV UU
  • C++ 中向量的 insert 和 emplace 有什么区别[重复]

    这个问题在这里已经有答案了 除了使用 emplace 进行单次插入和使用 insert in vector 进行多次插入之外 他们的实施还有其他区别吗 在这两种情况下 插入任何元素都会移动所有其他元素 std vector insert c
  • 如何在 Kubernetes 中公开 Ingress 以供外部访问?

    我在私有网络 私有服务器 不是 aws 或 google cloud 上有一个 kubernetes 集群 并且我创建了一个能够访问的服务 但是 我需要能够从集群外部访问 为此我创建了一个 Ingress并在集群中添加了 ingress n
  • PHP5-IMAP '我没有身体!'

    这对你来说是一个奇怪的事情 我正在使用Ipipi SMS到电子邮件服务将控制命令发送到PHP script 我可以将电子邮件发送到我的邮箱 然后使用以下命令阅读并显示它们PHP IMAP命令如以下代码段所示 overview imap fe
  • 在 Swift 中获取鼠标坐标

    斯威夫特新手在这里 我在完成一项本来应该是微不足道的任务时遇到了麻烦 我想要做的就是获取鼠标光标的 x y 坐标一经请求 我会比较喜欢not等待鼠标移动事件触发 然后才能获取指针的坐标 将不胜感激任何帮助 你应该看看 NSEvent 方法鼠
  • 使用 Node 更新(写入)单独 JS 文件中的对象

    我对 Node 还很陌生 正在绞尽脑汁地思考如何实现以下目标 我有一个如下所示的配置文件 various es imports export default input index src index ts Button src Butto
  • Shutil.move 删除了我所有的照片

    for i in os listdir if jpeg in i or png in i shutil move os path join os getcwd i my photos 我想将所有照片移动到一个名为 我的照片 的文件夹中 但该
  • 如何优化设计文档版本? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 关于SO here https stackoverflow com questions 36820 version control for wo
  • Hamcrest 使用“is”前缀 getter 方法对布尔字段进行断言

    我们想要断言自定义对象列表包含一个对象 该对象的某些字段具有特定值 并具有一系列如下断言 assertThat customObjectList hasItem hasProperty someField equalTo someValue
  • Canvas PutImageData 颜色丢失,无/低 alpha

    有一个 3x3 图像 CanvasPixelArray 是 12 24 48 255 12 24 48 255 12 24 48 255 12 24 48 255 12 24 48 255 12 24 48 255 12 24 48 255
  • gcc/gdb:如何在调试信息中嵌入源文件的绝对路径?

    我只是想知道我是否可以告诉 gcc 在调试信息中嵌入源文件的绝对路径 即使我像这样调用 gcc gcc g src somecode c o bin somecode o 正如我所看到的 gcc只存储你提供的内容 所以如果你提供一个相对路径
  • 神秘的 ESLint 解析错误

    在以下代码的第 4 行 ESLint 给我一个解析错误 意外令牌 我想知道为什么会出现这种情况 代码运行正常 我究竟做错了什么 import Component PropTypes from react export default cla
  • Oracle 支持全文搜索吗?

    Oracle 是否有相当于 MS SQL 全文搜索服务的服务 如果是这样 有人实施过它并有好的 坏的经验吗 甲骨文文本 http download oracle com docs cd B19306 01 server 102 b14220
  • 解压缩非常大的序列化对象并管理内存

    我有一个对象 其中包含大量用于报告的数据 为了将该对象从服务器发送到客户端 我首先在内存流中序列化该对象 然后使用 NET 的 Gzip 流对其进行压缩 然后 我将压缩对象作为 byte 发送到客户端 问题出在某些客户端上 当它们获取 by
  • 强制我的 heroku 应用程序使用 SSL (https)

    我有一个节点应用程序在 Heroku 上成功运行 我购买了加急 SSL 证书 一切正常 我访问 https 并得到一个完整的 绿色条 证明该网站正在通过 https 提供服务 然而 非 SSL 标准 http 仍然可用 如何强制应用程序通过
  • 使用 VS2012 RC 时,如果在 main() 退出后调用 std::thread::join() 则会挂起

    如果在 Ubuntu 12 04 上使用 Clang 3 2 或 GCC 4 7 编译 以下示例会成功运行 即不会挂起 但如果使用 VS11 Beta 或 VS2012 RC 编译 则会挂起 include