commit 8052900a3b2ce243e1273bec5ab55a8af7c1dc9f Author: Brecht Van Lommel Date: Tue Mar 31 14:04:50 2026 +0200 Fix: Mantaflow memory leak in PbArgs temporary storage diff --git a/extern/mantaflow/helper/pwrapper/pconvert.cpp b/extern/mantaflow/helper/pwrapper/pconvert.cpp index 5a7a32c5a73..7978032001b 100644 --- a/extern/mantaflow/helper/pwrapper/pconvert.cpp +++ b/extern/mantaflow/helper/pwrapper/pconvert.cpp @@ -324,53 +324,53 @@ template<> PbTypeVec fromPy(PyObject *obj) return vec; } -template T *tmpAlloc(PyObject *obj, std::vector *tmp) +template T *tmpAlloc(PyObject *obj, std::vector *tmp) { if (!tmp) throw Error("dynamic de-ref not supported for this type"); T *ptr = new T(fromPy(obj)); - tmp->push_back(ptr); + tmp->push_back([ptr]() { delete ptr; }); return ptr; } -template<> float *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> float *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> double *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> double *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> int *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> int *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> std::string *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> std::string *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> bool *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> bool *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> Vec3 *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> Vec3 *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> Vec3i *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> Vec3i *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> Vec4 *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> Vec4 *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } -template<> Vec4i *fromPyPtr(PyObject *obj, std::vector *tmp) +template<> Vec4i *fromPyPtr(PyObject *obj, std::vector *tmp) { return tmpAlloc(obj, tmp); } template<> -std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp) +std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp) { return tmpAlloc>(obj, tmp); } @@ -501,9 +501,9 @@ PbArgs::PbArgs(PyObject *linarg, PyObject *dict) : mLinArgs(0), mKwds(0) } PbArgs::~PbArgs() { - for (int i = 0; i < (int)mTmpStorage.size(); i++) - operator delete(mTmpStorage[i]); - mTmpStorage.clear(); + for (auto &fn : mTmpStorageCleanup) + fn(); + mTmpStorageCleanup.clear(); } void PbArgs::copy(PbArgs &a) diff --git a/extern/mantaflow/helper/pwrapper/pconvert.h b/extern/mantaflow/helper/pwrapper/pconvert.h index eda2f5b9632..857c306f586 100644 --- a/extern/mantaflow/helper/pwrapper/pconvert.h +++ b/extern/mantaflow/helper/pwrapper/pconvert.h @@ -20,6 +20,7 @@ # ifndef _PCONVERT_H # define _PCONVERT_H +# include # include # include # include @@ -36,8 +37,10 @@ struct ArgLocker { PyObject *getPyNone(); +using TmpCleanupFn = std::function; + // for PbClass-derived classes -template T *fromPyPtr(PyObject *obj, std::vector *tmp) +template T *fromPyPtr(PyObject *obj, std::vector *tmp) { if (PbClass::isNullRef(obj) || PbClass::isNoneRef(obj)) return 0; @@ -48,19 +51,19 @@ template T *fromPyPtr(PyObject *obj, std::vector *tmp) return (T *)(pbo); } -template<> float *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> double *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> int *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> std::string *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> bool *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> Vec3 *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> Vec3i *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> Vec4 *fromPyPtr(PyObject *obj, std::vector *tmp); -template<> Vec4i *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> float *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> double *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> int *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> std::string *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> bool *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> Vec3 *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> Vec3i *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> Vec4 *fromPyPtr(PyObject *obj, std::vector *tmp); +template<> Vec4i *fromPyPtr(PyObject *obj, std::vector *tmp); template<> -std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp); +std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp); template<> -std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp); +std::vector *fromPyPtr>(PyObject *obj, std::vector *tmp); PyObject *incref(PyObject *obj); template PyObject *toPy(const T &v) @@ -205,10 +208,10 @@ class PbArgs { visit(number, key); PyObject *o = getItem(key, false, lk); if (o) - return fromPyPtr(o, &mTmpStorage); + return fromPyPtr(o, &mTmpStorageCleanup); if (number >= 0) o = getItem(number, false, lk); - return o ? fromPyPtr(o, &mTmpStorage) : defarg; + return o ? fromPyPtr(o, &mTmpStorageCleanup) : defarg; } template inline T *getPtr(const std::string &key, int number = -1, ArgLocker *lk = nullptr) @@ -216,10 +219,10 @@ class PbArgs { visit(number, key); PyObject *o = getItem(key, false, lk); if (o) - return fromPyPtr(o, &mTmpStorage); + return fromPyPtr(o, &mTmpStorageCleanup); o = getItem(number, false, lk); if (o) - return fromPyPtr(o, &mTmpStorage); + return fromPyPtr(o, &mTmpStorageCleanup); errMsg("Argument '" + key + "' is not defined."); } @@ -250,7 +253,7 @@ class PbArgs { std::map mData; std::vector mLinData; PyObject *mLinArgs, *mKwds; - std::vector mTmpStorage; + std::vector mTmpStorageCleanup; }; } // namespace Manta