cmake-build-extension icon indicating copy to clipboard operation
cmake-build-extension copied to clipboard

Would SWIG example `normalize_numpy` leak memory?

Open adamryczkowski opened this issue 1 year ago • 2 comments

Here's a quote from the wrapper in bindings_swig/bingins.i:

    void normalize_numpy(double* in_1, unsigned size_in_1,
                         double** out_1, int* size_out_1)
    {
        const std::vector<double> vector(in_1, in_1 + size_in_1);

        auto result = mymath::normalize(vector);

        *out_1 = static_cast<double*>(malloc(result.size() * sizeof(double)));
        std::copy(result.begin(), result.end(), *out_1);

        *size_out_1 = result.size();
    }

I can see malloc. The question is when the vector is going to be deallocated on the Python side? Or would numpy do it implicitly (perhaps using Python's GC)?

adamryczkowski avatar May 23 '23 10:05 adamryczkowski

@adamryczkowski There won't be any leak.

normalize_numpy() is using the numpy typemap on line 45, which defines the output variable as an ARGOUTVIEWM_ARRAY1 — the M after ARGOUTVIEW stands for "Managed", and tells SWIG to not only create the returned Python object from the allocated C++ object's memory directly, without copying it (ARGOUTVIEW), but also to take ownership of that underlying object, and deallocate it once the Python object is deleted and it's no longer required (ARGOUTVIEWM).

A list of the available typemaps with very minimal descriptions is in the numpy documentation for numpy.i, and the more-explanatory blog post dead-linked there can be read using the wayback machine.

ferdnyc avatar Jun 02 '24 04:06 ferdnyc

(Actually, perhaps more informative is the SciPy Cookbook entry that was created, along with the typemaps in question, based on the automatic deallocation code originally published in that blog post.)

ferdnyc avatar Jun 02 '24 04:06 ferdnyc