# HG changeset patch # User John W. Eaton # Date 1638627192 18000 # Sat Dec 04 09:13:12 2021 -0500 # Branch stable # Node ID 3ed35b2f2be6a24bac98f4ce0281d524e7e02b91 # Parent dad899b0e3285d674c17f9390eb1efbdd9dc52dd With C++17, match malloc/free for MEX memory (bug #61472) * Array-fwd.h, Array.h: With C++17, change default allocator for Array class to be std::pmr::polymorphic_allocator. * mex.cc (mx_memory_resource): New class to manage MEX memory allocations when they are transferred to octave_value objects. (the_mx_memory_resource): New static object. (fp_to_ov, int_to_ov): Pass pointer to the_mx_memory_resource to Array constructor so that it will use free to release storage allocated with mxMalloc or mxRealloc after it is returned to Octave in an octave_value object. diff --git a/libinterp/corefcn/mex.cc b/libinterp/corefcn/mex.cc --- a/libinterp/corefcn/mex.cc +++ b/libinterp/corefcn/mex.cc @@ -27,6 +27,12 @@ # include "config.h" #endif +// #define DEBUG 1 + +#if DEBUG +# include +#endif + #include #include #include @@ -34,9 +40,12 @@ #include #include +#include #include #include +// Needed to instantiate Array objects with custom allocator. +#include "Array.cc" #include "f77-fcn.h" #include "lo-ieee.h" #include "oct-locbuf.h" @@ -253,12 +262,6 @@ extern "C" extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi); } -// #define DEBUG 1 - -#if DEBUG -# include -#endif - static void * xmalloc (size_t n) { @@ -310,6 +313,39 @@ max_str_len (mwSize m, const char **str) return max_len; } +#if __cplusplus >= 201703L +# include + +class mx_memory_resource : public std::pmr::memory_resource +{ +private: + + void * do_allocate (std::size_t bytes, size_t /*alignment*/) + { + void *ptr = xmalloc (bytes); + + if (! ptr) + throw std::bad_alloc (); + + return ptr; + } + + void do_deallocate (void* ptr, std::size_t /*bytes*/, + std::size_t /*alignment*/) + { + xfree (ptr); + } + + bool do_is_equal (const std::pmr::memory_resource& /*other*/) const noexcept + { + // FIXME: what should this really be doing? + return true; + } +}; + +static mx_memory_resource the_mx_memory_resource; +#endif + // ------------------------------------------------------------------ mxArray_base::mxArray_base (bool interleaved) @@ -2078,7 +2114,16 @@ protected: { ELT_T *ppr = static_cast (m_pr); + // We need the custom allocator here because we are transferring + // ownership of an array that was created with mxMalloc, mxCalloc, + // or mxRealloc to an Array object. + +#if __cplusplus >= 201703L + Array val (ppr, dv, &the_mx_memory_resource); +#else +# warning "relying on delete to release memory allocated by malloc" Array val (ppr, dv); +#endif maybe_disown_ptr (m_pr); @@ -2095,7 +2140,16 @@ protected: ELT_T *ppr = static_cast (m_pr); #if 0 + // FIXME: We will need to use a custom allocator here because we are + // transferring ownership of an array that was created with + // mxMalloc, mxCalloc, or mxRealloc to an Array object. + +#if __cplusplus >= 201703L + ARRAY_T val (ppr, dv, &the_mx_memory_resource); +#else +# warning "relying on delete to release memory allocated by malloc" ARRAY_T val (ppr, dv); +#endif maybe_disown_ptr (m_pr); #else @@ -2360,6 +2414,9 @@ private: T *ppr = static_cast (m_pr); + // We allocate in the Array constructor and copy here, so we + // don't need the custom allocator for this object. + Array> val (dv); std::complex *ptr = val.fortran_vec (); diff --git a/liboctave/array/Array-fwd.h b/liboctave/array/Array-fwd.h --- a/liboctave/array/Array-fwd.h +++ b/liboctave/array/Array-fwd.h @@ -28,7 +28,17 @@ #include "octave-config.h" +#if __cplusplus >= 201703L +# include + +template > +class OCTARRAY_API Array; + +#else + template > class OCTARRAY_API Array; #endif + +#endif diff --git a/liboctave/array/Array.h b/liboctave/array/Array.h --- a/liboctave/array/Array.h +++ b/liboctave/array/Array.h @@ -789,7 +789,12 @@ public: //! Apply function fcn to each element of the Array. This function //! is optimized with a manually unrolled loop. +#if __cplusplus >= 201703L + template > +#else template > +#endif Array map (F fcn) const { @@ -821,12 +826,20 @@ public: //@{ //! Overloads for function references. +#if __cplusplus >= 201703L + template > +#else template > +#endif Array map (U (&fcn) (T)) const { return map (fcn); } +#if __cplusplus >= 201703L + template > +#else template > +#endif Array map (U (&fcn) (const T&)) const { return map (fcn); }