简体   繁体   English

在应用程序结束时创建 cv::Ptr 会导致异常

[英]Creating cv::Ptr cause an exception at the end of the application

I am working with openCV arUco markers to detect some markers.我正在使用 openCV arUco 标记来检测一些标记。 So I generated pre-defined dictionary and saved it in a file.所以我生成了预定义的字典并将其保存在一个文件中。 However the aruco::detectMarkers can only get Ptr<aruco::Dictionary> .然而aruco::detectMarkers只能得到Ptr<aruco::Dictionary> So I create a Ptr<aruco::Dictionary> object and sent to the constructor the address of the object itself.所以我创建了一个Ptr<aruco::Dictionary> object 并将 object 本身的地址发送给构造函数。 This is causing to exception at the end of the application.这导致应用程序结束时出现异常。 How can I solve it?我该如何解决?

Here is my (simplified) code:这是我的(简化的)代码:

#include <opencv2/highgui.hpp>
#include <opencv2/aruco/charuco.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;

aruco::Dictionary ReadDictionaryFromFile(std::string fileName)
{
    cv::FileStorage fileStorage(fileName, cv::FileStorage::READ);
    Mat bytesList;
    int markerSize;
    int maxCorrectionBits;
    fileStorage\["markerSize"\] >> markerSize;
    fileStorage\["maxCorrectionBits"\] >> maxCorrectionBits;
    fileStorage\["bytesList"\] >> bytesList;
    fileStorage.release();
    aruco::Dictionary dictionary = cv::aruco::Dictionary(bytesList, markerSize, maxCorrectionBits);

    return dictionary;
}

int main(int argc, char *argv\[\])
{
    //Detector parameters:
    Ptr<aruco::DetectorParameters> detectorParams = aruco::DetectorParameters::create();
    
    //This works but I am afraid will generate another dictionary on another machine
    //Ptr<aruco::Dictionary> dictionary = aruco::generateCustomDictionary(1, 4);

    //This works but generate exception when app is terminated
    aruco::Dictionary dictionaryTemp = ReadDictionaryFromFile("Dictionary.yml");
    Ptr<aruco::Dictionary> dictionary = cv::Ptr<aruco::Dictionary>(&dictionaryTemp);

    while (true)
    {
        if (camera.grab(image) != SUCCESS)
        {
            cout << "error on grab()" << std::endl;
            return 0;
        }
        
        vector< int > ids;
        vector< vector< Point2f > > corners, rejected;
        vector< Vec3d > rvecs, tvecs;

        // detect markers and estimate pose
        aruco::detectMarkers(image, dictionary, corners, ids, detectorParams, rejected);

        aruco::drawDetectedMarkers(image, corners, ids);

        imshow("out", image);
        char key = (char)waitKey(1);
        
        if (key == 'q')
        {
            break;
        }
    }

    return 0;
}

Here is the exception:这是一个例外: 例外

According to cv::Ptr documentation:根据 cv::Ptr 文档:

Template class for smart pointers with shared ownership.用于共享所有权的智能指针的模板 class。

A Ptr pretends to be a pointer to an object of type T. Unlike an ordinary pointer, however, the object will be automatically cleaned up once all Ptr instances pointing to it are destroyed. Ptr 伪装成指向 T 类型的 object 的指针。然而,与普通指针不同的是,一旦指向它的所有 Ptr 实例被销毁,object 将被自动清理。

You are creating an object on the stack, and then you are using it to construct the smart pointer.您正在堆栈上创建 object,然后使用它来构造智能指针。 The smart pointer is not owning the object at all.智能指针根本不拥有 object。

    aruco::Dictionary dictionaryTemp = ReadDictionaryFromFile("Dictionary.yml");
    Ptr<aruco::Dictionary> dictionary = cv::Ptr<aruco::Dictionary>(&dictionaryTemp);

At the end of the scope, which in your case it is the end of the main, dictionaryTemp will go out of scope and destroy the object.在 scope 的末尾,在您的情况下,它是主要的末尾,dictionaryTemp 将从 scope 中取出 go 并破坏 ZA8CF9669FDE69211AC

After that, the smart pointer dictionary will go out of scope as well, but now the pointer is dangling and almost anything can happen.之后,智能指针字典将从 scope 中取出 go,但现在指针悬空,几乎任何事情都可能发生。

Modify your code to give true ownership to the smart pointer:修改您的代码以赋予智能指针真正的所有权:

Ptr<aruco::Dictionary> ReadDictionaryFromFile(std::string fileName)
{
    ...
    return cv::Ptr<aruco::Dictionary>(
         new cv::aruco::Dictionary(bytesList, markerSize, maxCorrectionBits));
}

For consideration related with exception safety, in modern, c++ writing the keyword new is rare and the best practise dictates to use a wrapper function called std::make_shared (which is working with the std::shared_ptr, there are similar function for others smart pointer). For consideration related with exception safety, in modern, c++ writing the keyword new is rare and the best practise dictates to use a wrapper function called std::make_shared (which is working with the std::shared_ptr, there are similar function for others smart指针)。 I am not familiar with cv::Ptr and I wasn't able to find an equivalent for it.我不熟悉 cv::Ptr 并且我无法找到它的等价物。 But it worth to be aware of it.但值得了解它。

Get familiar with RAII https://en.cppreference.com/w/cpp/language/raii and exception safety https://www.stroustrup.com/except.pdf熟悉 RAII https://en.cppreference.com/w/cpp/language/raii和异常安全https://www.stroustrup.com/except.Z437175BA4191749404E1D93

Also, you may want to familiarize with different types of smart pointers Smart pointers: who owns the object?此外,您可能想熟悉不同类型的智能指针智能指针:谁拥有 object?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM