访问私有实例变量c++时出现分段错误

segmentation fault on accessing private instance variable c++

本文关键字:分段 错误 c++ 实例 变量 访问      更新时间:2023-10-16

我在处理OpenCV/C++项目时遇到了一个奇怪的问题。我只是想在ClassifierManager类中使用KNN。因此,我使用cv::flann::Index * knnFlan,它在构造函数中初始化,如下所示:

.h

class ClassifierManager
{
private:
    Mat dataToTrain;
    Mat classesData;
    int kNearestNeighborToConsider;
    CvKNearest *classifier;
    cv::flann::Index *knnFlan;
public:
    ClassifierManager();
    ClassifierManager(Mat trainData, Mat dataClasses, int numberOfNearestNeighborToConsider);
    vector < vector <int> > annotateTheTilesInImages(Mat trainData, vector < vector < vector <double> > > featuresPerImageForTiles, int numberOfNearestNeighborToConsider);
};

.m

ClassifierManager::ClassifierManager()
{}
ClassifierManager::ClassifierManager(Mat trainData, Mat dataClasses, int numberOfNearestNeighborToConsider)
{
//    dataToTrain = trainData;
//    classesData = dataClasses;
    kNearestNeighborToConsider = numberOfNearestNeighborToConsider;
    try
    {
        dataClasses.convertTo(dataClasses,CV_32FC1);
        trainData.convertTo(trainData,CV_32FC1);
        knnFlan = new flann::Index( trainData, flann::KDTreeIndexParams(1), cvflann::FLANN_DIST_EUCLIDEAN);
    } catch (std::exception& ex)
    {
        cout << ex.what() << endl;
    }
}
vector < vector <int> > ClassifierManager::annotateTheTilesInImages( vector < vector < vector <double> > > featuresPerImageForTiles, int numberOfNearestNeighborToConsider)
{
    vector < vector <int> > resultForImagePerTile;
    for (int imageIndex = 0; imageIndex < featuresPerImageForTiles.size(); imageIndex++ )
    {
        vector < vector <double> >featuresPerTile = featuresPerImageForTiles[imageIndex];
        vector <int>  resultPerTile;
        for (int tileIndex = 0; tileIndex < featuresPerTile.size(); tileIndex ++)
        {
            vector <double> featureForTile = featuresPerTile[tileIndex];
            // estimate the response and get the neighbors' labels
            cv::Mat results, dists;
            Mat featureOfTileInMat(featureForTile);
            featureOfTileInMat.convertTo(featureOfTileInMat, CV_32FC1);
            featureOfTileInMat = featureOfTileInMat.t();
            //int result = classifier->find_nearest(featureOfTileInMat,numberOfNearestNeighborToConsider, &results, 0, &neighborResponses, &dists);
            //float percentageOfInstrumentForThisWindow = (float(countNonZero(neighborResponses)) / numberOfNearestNeighborToConsider) * 100;
            knnFlan->knnSearch(featureOfTileInMat, results, dists, numberOfNearestNeighborToConsider, flann::SearchParams());
              //..... Things to add

        }
    }
    return resultForImagePerTile;
}

主.m

/*Step 9: Knn Classifier train data */
Mat trainData = VectorUtility <double>::toMat(featuresPerTile);
Mat dataClasses = VectorUtility <int>::toMat(annotationPerTile);
ClassifierManager classifier(trainData, dataClasses, kNearestNeighbor);
/*Step 10: Annotation Step*/
vector < vector <int> > resultsForEachImagePerTile = classifier.annotateTheTilesInImages(trainData, featuresPerImageForTiles, kNearestNeighbor);

问题是,当我尝试从main调用annotateTheTilesInImages时,项目会抛出一个无法被try-catch指令捕获的segmentation fault,从而在knnFlan->knnSearch(featureOfTileInMat, results, dists, numberOfNearestNeighborToConsider, flann::SearchParams());上崩溃。在我看来,如何管理类中的实例变量存在问题,但不确定是什么!感谢您的帮助。

@以上更新只是删除了不必要的代码

@编辑:正确的代码:

.h

class ClassifierManager
{
private:
    Mat dataToTrain;
    Mat classesData;
    int kNearestNeighborToConsider;
    CvKNearest *classifier;
    cv::flann::Index *knnFlan;
public:
    ClassifierManager();
    ClassifierManager(Mat &trainData, Mat &dataClasses, int numberOfNearestNeighborToConsider);
    vector < vector <int> > annotateTheTilesInImages(Mat trainData, vector < vector < vector <double> > > featuresPerImageForTiles, int numberOfNearestNeighborToConsider);
};

.m

ClassifierManager::ClassifierManager()
{}
ClassifierManager::ClassifierManager(Mat &trainData, Mat &dataClasses, int numberOfNearestNeighborToConsider)
{
    dataToTrain = trainData;
    classesData = dataClasses;
    kNearestNeighborToConsider = numberOfNearestNeighborToConsider;
    try
    {
        dataToTrain .convertTo(dataToTrain ,CV_32FC1);
        knnFlan = new flann::Index( dataToTrain , flann::KDTreeIndexParams(1), cvflann::FLANN_DIST_EUCLIDEAN);
    } catch (std::exception& ex)
    {
        cout << ex.what() << endl;
    }
}
....

代码中还有一些问题(例如,我看不到任何CvKNearest *classifier初始化的地方),但我认为您的问题是由以下原因引起的:

通过传递trainDataannotateTheTilesInImages,而不是通过reference常量引用。这意味着该函数中的trainData另一个对象(当然具有相同的数据-OpenCV支持隐式共享),但对于flann::Index来说,这可能是一个问题。

EDIT:很抱歉,我的意思是您将矩阵按值传递给ClassifierManager构造函数,而不仅仅是annotateTheTilesInImages。例如,您传递给flann::Index构造函数的cv::Mat对象不存在于ClassifierManager构造函数之外(尽管数据仍由其他cv::Mat对象处理)。