c++ - 在新线程中调用 OpenCV 函数 Canny() 会导致分段错误
问题描述
我正在开发一个服务器应用程序,它基于客户端请求使用 OpenCV 库执行某些图像处理操作。应用程序的性质要求使用多个线程。最近我一直在处理一个非常顽固的错误,它导致了段错误。我能够将发生分段错误的代码部分归零。
这是最小的实现。
#include <iostream>
#include <thread>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
int main() {
cv::Mat img_input = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
cv::Mat img_output = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
int i = 1;
while (i < 100) {
std::cout << "- - - - - - - - - - - - - - " << i++ << std::endl;
std::thread([&]() {
std::cout << "Thread started." << std::endl;
cv::Canny(img_input, img_output, 10, 20);
std::cout << "Thread finished." << std::endl;
}).join();
std::cout << "Thread joined." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(150));
}
return 0;
}
并且程序失败,有 2 个不同的输出。有了这个输出......
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Segmentation fault (core dumped)
..或与这个。
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Thread finished.
Segmentation fault (core dumped)
让我分享一下我的其他发现。段错误仅发生在我安装了 OpenCV 版本 3.3.0-dev 的嵌入式 linux 设备(Toradex Colibri iMX6 - 计算机模块)上。仅当我在新线程中使用 Canny() 函数时才会导致段错误。我也尝试过调用其他 OpenCV 函数,但它们都没有产生任何错误。
当我在我的 PC(Ubuntu 16.04,OpenCV 版本 3.3.0)上运行程序时,没有发生段错误。
有任何想法吗?
******更新 1 ******
我试图遵循评论中的一些建议。但是问题仍然存在。
我将 Mat 变量移动到每个线程的范围内,以使它们成为线程的本地变量。我还添加了一些额外的睡眠时间来等待线程完成。
这是我的新实现。
#include <iostream>
#include <thread>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
void run() {
cv::Mat img_input = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
cv::Mat img_output = cv::Mat::zeros(cv::Size(240, 320), CV_8UC1);
std::cout << "Thread started." << std::endl;
cv::Canny(img_input, img_output, 10, 20);
std::cout << "Thread finished." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int main() {
int i = 1;
while (i < 100) {
std::cout << "- - - - - - - - - - - - - - " << i++ << std::endl;
std::thread t1(run);
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Waiting to join thread." << std::endl;
t1.join();
std::cout << "Thread joined." << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return 0;
}
输出再次在...之间变化
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Waiting to join thread.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Thread finished.
Segmentation fault (core dumped)
... 和 ...
- - - - - - - - - - - - - - 1
Thread started.
Thread finished.
Waiting to join thread.
Thread joined.
- - - - - - - - - - - - - - 2
Thread started.
Segmentation fault (core dumped)
******更新 2 ******
我在这里找到了一个类似问题的帖子。建议在代码中添加以下行可以解决问题。
cv::setNumThreads(0);
我在main()函数的开头添加了这一行,似乎它解决了分段错误的问题。这是否有助于解释程序发生了什么?
目前这似乎是一个很好的快速解决方案,但在我接受它作为合适的解决方案之前,我想了解它的背景。谁能解释为什么段错误不再发生?
有更好的解决方案吗?
解决方案
事实证明,将线程数设置为 0 或 1 即可解决问题(不再发生段错误)。这是通过以下两行代码之一完成的。
cv::setNumThreads(0); // Setting the number of thread to 0.
cv::setNumThreads(1); // Setting the number of thread to 1.
我不太了解 OpenCV 库,无法理解为什么会发生段错误以及为什么这条线可以解决问题,但此时我对结果感到满意,并将此问题标记为已回答。希望这对其他人有帮助。
推荐阅读
- scala - 貘自定义编解码器
- python - tkinter 中的 .bind() 迟到了
- python - 如何在 Django 中应用从数据库中获取的文本样式?
- perl - perl 5.6 版中的 500 SSL 协商失败
- wordpress - 如何更改 Wordpress divi 主题中的背景图像?
- types - 我应该使用什么类型声明来创建自己的 HashMap contains 方法?
- reactjs - 反应管理员:
始终显示为“活动” - python - 在 SQL 表中插入 key/id 而不是 value
- c - 如何分配更少的内存并且它仍然有效?
- android - 如何检查 onCreate android fetch 库中的下载是否完成?