C++ 单线程工作,在新线程上它调用“abort()”

Posted

技术标签:

【中文标题】C++ 单线程工作,在新线程上它调用“abort()”【英文标题】:C++ single threaded works, on new thread it calls "abort()" 【发布时间】:2016-09-28 08:38:05 【问题描述】:

我遇到的问题很可能与线程或互斥锁有关:

当我直接在主方法中调用自定义方法时,它会起作用并给出结果。但是,计算需要大约 900 毫秒。所以我想做一个只做这个计算并在之后显示结果的线程。

这个时候项目比较大,我尽量给出尽可能接近原始的伪代码。

更多背景信息:我从相机流式传输深度图像,并希望在此图像上使用细化算法。为此使用 OpenCV 3.1.0 和 MSVC 2015(均为 32 位)。

int main()

 //init camera, read images etc...
 Mat copyOfImage = dephtImage->clone();
 applyThreadedThinning(&copyOfImage);

 return 0;

这个版本运行良好。 如果我这样调用该方法:

std::thread t1(&applyThreadedThinning,&copyOfImage);

它说 "调试错误!

程序:.... *.exe

abort() 已被调用

(按重试调试应用程序)"

我无法想象为什么它可以在没有线程的情况下工作,但在使用线程时却不行。 调试有点复杂,我只是在每一行后面加上“step into”,然后等到它发出这个错误消息。一旦我隔离了导致此错误的代码行,我该怎么办?

【问题讨论】:

您是否尝试过点击“重试”来调试应用程序?然后看看堆栈跟踪? 如果我点击“重试”,它会在方法“static bool __cdecl issue_debug_notification(wchar_t const* const message) throw()”处停止。堆栈跟踪是“调用堆栈”? 那么您需要检查以前的功能。如果您在任何时候处于 std::thread 的析构函数中,那么已经在这里的答案解释了为什么会发生这种情况。 【参考方案1】:

一个 c++ std::thread 对象需要知道它应该做什么,以防它被破坏(超出范围)。

有 2 个选项:join 等待线程完成或 detach 将线程与对象分离。

因为这两个选项都是有效的,所以决定它们都不会在销毁时隐含,并且当您销毁 std::thread 对象而不首先调用其中一个函数时,将抛出一个断言(中止)。

如果您想在对象超出范围之前等待线程完成调用t1.join()

如果您想将自己与线程分离并让它在某个时刻完成,您不必关心在对象超出范围之前调用t1.detach()

【讨论】:

+1 用于提供这两个选项,但根据 OP 的要求,听起来像 t1.detach() 是需要的。请注意,在这个简单的示例中,不会向用户提供工作线程已完成的任何指示,因为main() 将在工作线程完成之前退出。 是的,他说这是简化的“伪代码”,因为我不知道我列出的要求。不过这真的取决于情况。 分离()确实帮助了我。只要我不按键,我的主线程就处于一个while循环中。似乎线程正在重新启动,而旧线程尚未完成。同样在调试时,我注意到范围存在一些问题(指向图像的指针是空指针,但在单线程上它不是空指针)。我需要阅读有关此主题的更多信息,然后重试。 detach 这样做。它分离。而加入等待。您需要决定两种功能之一。 c++11 线程都是关于干净线程处理的。您也不能轻易地从外部“杀死”线程。线程需要能够通过超出范围来结束自己。所以线程等中没有无限循环。【参考方案2】:

您应该在主函数中等待,直到线程完成。

...
t1.join();
return 0;

【讨论】:

a join 等待线程完成。你的线程会在某个时候结束吗? 看来这就是问题所在。单线程方法正常返回结果。如果我在自己的线程中启动相同的方法,则该线程由于某种原因无法完成。如上所述,我认为这与“超出范围”有关。【参考方案3】:

解决了 abort() 问题。该问题似乎与范围/智能指针有关。只需将每个 cv::Mat* 替换为 cv::Mat(无指针)并针对更改的类型调整代码。

就我而言,这是一个解决方案。感谢@Hayt 的解释,它确实加快了我的进程。

【讨论】:

以上是关于C++ 单线程工作,在新线程上它调用“abort()”的主要内容,如果未能解决你的问题,请参考以下文章

Thread.Abort 方法

如何关闭嵌套在线程内的线程?

C++:线程池比单线程慢?

在新窗口 C++ 中创建线程

单例模式详解

C# 在新线程中调用方法