c++ - 在新线程中调用 OpenCV 函数 Canny() 会导致段错误

标签 c++ linux multithreading opencv segmentation-fault

我正在开发一个基于客户端请求的服务器应用程序,它使用 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 变量移动到每个线程的范围内,使它们成为线程的本地变量。我还添加了一些额外的 sleep 时间来等待线程完成。

这是我的新实现。

#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 ******

我发现了一个有类似问题的帖子 here .建议在代码中添加以下行可以解决问题。

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 库的了解还不够深,无法理解为什么会出现段错误以及为什么这一行可以解决问题,但此时我对结果很满意,并将把这个问题标记为已回答。希望这对其他人有帮助。

关于c++ - 在新线程中调用 OpenCV 函数 Canny() 会导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52071907/

相关文章:

linux - 如何将 cppcheck 的输出重定向到文件中?

linux - 连接文件 awk/linux

linux - 使用 opencv_createsamples 中止(核心转储)

java - 在线程中运行时在不同的时间得到不同的结果

c++ - 将 Alpha Beta 实现为 Minimax

c++ - 在不破坏对象的情况下创建对象映射

python - C++ 到 Python 的行尾

c++ - 为什么 MSVC 的自动矢量化不使用 AVX2?

multithreading - 如何在不卡住的情况下读取 blobfield?

python - 我会遇到 python 的全局解释器锁的问题吗?