flann-lib / flann

Fast Library for Approximate Nearest Neighbors
http://people.cs.ubc.ca/~mariusm/flann
Other
2.24k stars 650 forks source link

free() function non-existent for flann::Matrix in C++ #325

Open meder411 opened 7 years ago

meder411 commented 7 years ago

In testing the C++ example from the docs, I tried to call

distMat.free();
queryMat.free();
indicesMat.free();
datasetMat.free();

and got the errors

/path/to/file:93:13: error: ‘class flann::Matrix<int>’ has no member named ‘free’
   indicesMat.free();
              ^
/path/to/file:94:11: error: ‘class flann::Matrix<double>’ has no member named ‘free’
   distMat.free();
           ^
/path/to/file:95:12: error: ‘class flann::Matrix<double>’ has no member named ‘free’
   queryMat.free();
            ^
/path/to/file:96:14: error: ‘class flann::Matrix<double>’ has no member named ‘free’
   datasetMat.free();

When I leave out these commands, the code works just fine. I'm just worried I'm creating memory leaks. Why might this be occurring?

If it helps, here is the rest of the code:

int k = 50;

std::vector<double> data;
// ...fill the data vector...

// Build dataset matrix
flann::Matrix<double> datasetMat(data.data(), data.size(), 3);

// Allocate query matrix
std::vector<double> query(data);
flann::Matrix<double> queryMat(query.data(), data.size(), 3);

// Allocate indices matrix
std::vector<int> indices;
indices.reserve(data.size() * k);
flann::Matrix<int> indicesMat(indices.data(), data.size(), k);

// Allocate destination matrix for nearest neighbors
std::vector<double> dist;
dist.reserve(data.size() * k);
flann::Matrix<double> distMat(dist.data(), data.size(), k);

// Build 4 randomized KD-trees
flann::Index<flann::L2<double> > index(datasetMat, flann::KDTreeIndexParams(4));
index.buildIndex();

// Perform KNN search over the pointcloud
index.knnSearch(queryMat, indicesMat, distMat, k, flann::SearchParams(128));

distMat.free();
queryMat.free();
indicesMat.free();
datasetMat.free();
wbrandenburger commented 7 years ago

Hi,

flann::Matrix matrix(...)offers a Pointer matrix.ptr(). This ptr is directet onto the beginning of the corresponding array. That means with delete[] matrix.ptr() you can destroy the object. But I think you cant use free! There is no use of malloc(). Why are you using free?

meder411 commented 7 years ago

I'm not sure why I'd need free. I have no leaks or anything. It's just that the C++ example provided in the docs uses it, so I was curious why it wasn't available.

wbrandenburger commented 7 years ago

Ok. Dont use free, because you should allocate the memory with new. But all roads lead to rome, i havent tried it so far but it must be possible that you allocate the memory with malloc. But then you have to use the deallocation in this way free(distMat.ptr()), or there is a old version of FLANN where in matrix.h the function free is offered...

Greets from Munich

meder411 commented 7 years ago

I actually found that the more memory-safe C++(03+) way to do it is to allocate space using std::vector rather than with new or malloc. For example:

std::vector<double> distances;
distances.reserve(<necessary size>);

Then you can just provide the pointer to the vector data using distances.data(). I believe it was with C++03 that the standard ensures that vectors are contiguous in memory. Then you can rely on the std::vector destructor to handle any deletion instead of worrying about delete or free().

The only downside appears to be that, in the case of tight memory constraints, you are giving up complete control of your memory allocation. This is because myVec.reserve(n) guarantees at least a capacity of n, but its own optimizations may lead to allocations of more than n blocks in memory. See the docs.

The reason for my question was really because I thought I may have been missing something when reading through the docs and saw that they used some free() function.

mariusmuja commented 7 years ago

flann::Matrix is just a wrapper around a memory buffer, it doesn't do any allocation/de-allocation. You should handle do the memory de-allocation yourself. In the example above, the std::vector class will take care of de-allocating the memory.