thelfer / MFrontGenericInterfaceSupport

This project aims at providing support for MFront generic behaviours. This project can be embedded in open-source and propriary sofware
37 stars 35 forks source link

Memory leakage in python bindings #46

Closed bleyerj closed 4 years ago

bleyerj commented 4 years ago

There seems to be memory leakage problems when running some mgis.fenics demo (phase-field example at least)

thelfer commented 4 years ago

The trouble is in the mgis_convert_to_span which relies on the PyArray_FROM_OTF function to retrieve the data associated with an numpy array. I misread the documentation of this function and though it only retrieves the pointer of the numpy object, but it does more:

In both cases, the counter of the returned object must be decreased at the end of the function, which I did not. Hence the memory leak.

The following implementation shall work:

    mgis::span<mgis::real> mgis_convert_to_span(
        const boost::python::object& o) {
      PyArrayObject* a = nullptr;
      if (!PyArg_ParseTuple(o.ptr(), "O!", &PyArray_Type, &a)) {
        mgis::raise(
            "convert_to_span: argument not convertible to PyArrayObject");
      }
      if (a->descr->type_num != NPY_DOUBLE) {
        mgis::raise("convert_to_span: invalid numpy object");
      }
      if (a == nullptr) {
        mgis::raise(
            "convert_to_span: argument not convertible to PyArrayObject");
      }
      // number of dimensions
      const auto nd = PyArray_NDIM(a);
      if (nd != 1) {
        mgis::raise("convert_to_span: expected one dimensional array");
      }
      auto* const shape = PyArray_DIMS(a);
      const auto n = shape[0];
      auto* const values = static_cast<double*>(PyArray_GETPTR1(a, 0));
      return {values, static_cast<mgis::span<mgis::real>::index_type>(n)};
    }  // end of mgis_convert_to_span
thelfer commented 4 years ago

Fixed in master and rliv-1.1