Yonatan
Yonatan

Reputation: 51

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

I am working with openCV arUco markers to detect some markers. So I generated pre-defined dictionary and saved it in a file. However the aruco::detectMarkers can only get Ptr<aruco::Dictionary>. So I create a Ptr<aruco::Dictionary> object and sent to the constructor the address of the object itself. 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: exception

Upvotes: 0

Views: 493

Answers (1)

Alessandro Teruzzi
Alessandro Teruzzi

Reputation: 3978

According to cv::Ptr documentation:

Template class for smart pointers with shared ownership.

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.

You are creating an object on the stack, and then you are using it to construct the smart pointer. The smart pointer is not owning the object at all.

    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.

After that, the smart pointer dictionary will go out of scope as well, but now the pointer is dangling and almost anything can happen.

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). I am not familiar with cv::Ptr and I wasn't able to find an equivalent for it. 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

Also, you may want to familiarize with different types of smart pointers Smart pointers: who owns the object?

Upvotes: 1

Related Questions