Merge pull request #19045 from alalek:issue_17553

* flann: avoid dangling pointers on lost features data

* flann: fix Index::load()
pull/19087/head
Alexander Alekhin 4 years ago committed by GitHub
parent 8ac304517e
commit a04479746a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      modules/features2d/test/test_nearestneighbors.cpp
  2. 3
      modules/flann/include/opencv2/flann/miniflann.hpp
  3. 25
      modules/flann/src/miniflann.cpp

@ -123,7 +123,7 @@ void NearestNeighborTest::run( int /*start_from*/ ) {
Mat desc( featuresCount, dims, CV_32FC1 );
ts->get_rng().fill( desc, RNG::UNIFORM, minValue, maxValue );
createModel( desc );
createModel( desc.clone() ); // .clone() is used to simulate dangling pointers problem: https://github.com/opencv/opencv/issues/17553
tempCode = checkGetPoints( desc );
if( tempCode != cvtest::TS::OK )

@ -169,10 +169,13 @@ public:
CV_WRAP cvflann::flann_algorithm_t getAlgorithm() const;
protected:
bool load_(const String& filename);
cvflann::flann_distance_t distType;
cvflann::flann_algorithm_t algo;
int featureType;
void* index;
Mat features_clone; // index may store features pointer internally for searching, so avoid dangling pointers: https://github.com/opencv/opencv/issues/17553
};
} } // namespace cv::flann

@ -390,14 +390,18 @@ void Index::build(InputArray _data, const IndexParams& params, flann_distance_t
CV_INSTRUMENT_REGION();
release();
// Index may reuse 'data' during search, need to keep it alive
features_clone = _data.getMat().clone();
Mat data = features_clone;
algo = getParam<flann_algorithm_t>(params, "algorithm", FLANN_INDEX_LINEAR);
if( algo == FLANN_INDEX_SAVED )
{
load(_data, getParam<String>(params, "filename", String()));
load_(getParam<String>(params, "filename", String()));
return;
}
Mat data = _data.getMat();
index = 0;
featureType = data.type();
distType = _distType;
@ -462,6 +466,8 @@ void Index::release()
{
CV_INSTRUMENT_REGION();
features_clone.release();
if( !index )
return;
@ -785,9 +791,20 @@ bool loadIndex(Index* index0, void*& index, const Mat& data, FILE* fin, const Di
bool Index::load(InputArray _data, const String& filename)
{
Mat data = _data.getMat();
bool ok = true;
release();
// Index may reuse 'data' during search, need to keep it alive
features_clone = _data.getMat().clone();
Mat data = features_clone;
return load_(filename);
}
bool Index::load_(const String& filename)
{
Mat data = features_clone;
bool ok = true;
FILE* fin = fopen(filename.c_str(), "rb");
if (fin == NULL)
return false;

Loading…
Cancel
Save