首页 > 解决方案 > Segmentation fault on using Eigen::MatrixXf as function return type

问题描述

I'm trying to return a value of type Eigen::MatrixXf, but this results into a segmentation fault. Trying to debug, I've found that if return type is something else like a float or int with a corresponding return value in the function, the function runs successfully. I have tried the diagnose the problem from the Eigen documentation from here, but without any help.

MatrixXf& create_V_matrix(cv::Mat H) {
    // Gather V matrix
    MatrixXf v11 = get_vij_matrix(H, 0, 0);
    MatrixXf v12 = get_vij_matrix(H, 0, 1);
    MatrixXf v22 = get_vij_matrix(H, 1, 1);
    MatrixXf V;
    V << v12.transpose(),
        (v11-v12).transpose();
    return V;
}

MatrixXf get_vij_matrix(cv::Mat H, int i, int j) {
    // Create v matrix at i and j
    MatrixXf vij;
    vij <<  H.at<float>(0, i)*H.at<float>(0, j),
            H.at<float>(0, 1)*H.at<float>(1, j) +
            H.at<float>(1, i)*H.at<float>(0, j),
            H.at<float>(1, i)*H.at<float>(1, j),
            H.at<float>(2, i)*H.at<float>(0, j) +
            H.at<float>(0, i)*H.at<float>(2, j),
            H.at<float>(2, i)*H.at<float>(1, j) +
            H.at<float>(1, i)*H.at<float>(2, j),
            H.at<float>(2, i)*H.at<float>(2, j);
    return vij;
}

This results in a Segmentation fault(core dumped) when the create_V_matrix(cv::Mat H) is called.

标签: c++opencveigen3

解决方案


In your function et_vij_matrix, you need to set the size of the MatrixXf vij before using operator << to assign values. Otherwise, the allocated storage for vij has a zero size and your assignments are going to be out of bounds. I counted 6 values you're trying to assign, so vij.resize(1,6), vij.resize(2,3), vij.resize(3,2), or vij.resize(6,1) is required before the assignments.

Likewise, your matrix V is not resized before assigning the values from v11 & v12.

Finally, as noted by PeterT, you're create_V_matrix returns a MatrixXf& reference to a local variable, which is undefined behavior. While it might work, it is not required to. See this Q&A for a great explanation. If you're worried about the copy, you can and should rely on RVO/copy elision to remove the pointless copy.


推荐阅读