From f4480c60ce1b30d766c98ca5520d99d9ddf9456e Mon Sep 17 00:00:00 2001 From: Jurgen Lentz Date: Fri, 18 Oct 2024 15:24:33 +0200 Subject: [PATCH] fix memory leaks --- amplpy/ampl.pyx | 4 +++- amplpy/dataframe.pxi | 1 - amplpy/entity.pxi | 11 +++++++++++ amplpy/parameter.pxi | 9 +++++++-- amplpy/util.pxi | 4 +++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/amplpy/ampl.pyx b/amplpy/ampl.pyx index 40c525a..52aa118 100644 --- a/amplpy/ampl.pyx +++ b/amplpy/ampl.pyx @@ -515,7 +515,9 @@ cdef class AMPL: """ cdef campl.AMPL_VARIANT* v PY_AMPL_CALL(campl.AMPL_GetValue(self._c_ampl, scalar_expression.encode('utf-8'), &v)) - return to_py_variant(v) + py_variant = to_py_variant(v) + campl.AMPL_VariantFree(&v) + return py_variant def set_data(self, data, set_name=None): """ diff --git a/amplpy/dataframe.pxi b/amplpy/dataframe.pxi index 1351d87..c9f5dd2 100644 --- a/amplpy/dataframe.pxi +++ b/amplpy/dataframe.pxi @@ -36,7 +36,6 @@ cdef class Row(object): def __getitem__(self, key): cdef campl.AMPL_VARIANT* v - #campl.AMPL_DataFrameGetColumnIndex(self._df, key.encode('utf-8'), &column_index) campl.AMPL_DataFrameElement(self._df, self._index, key, &v) return to_py_variant(v) diff --git a/amplpy/entity.pxi b/amplpy/entity.pxi index 429c6f4..56ad2c9 100644 --- a/amplpy/entity.pxi +++ b/amplpy/entity.pxi @@ -48,6 +48,10 @@ cdef class Entity(object): entity.wrap_function = campl.AMPL_UNDEFINED return entity + #def __dealloc__(self): + # if self._index is not NULL: + # campl.AMPL_TupleFree(&self._index) + def to_string(self): cdef char* output_c campl.AMPL_EntityGetDeclaration(self._c_ampl, self._name.encode('utf-8'), &output_c) @@ -179,6 +183,7 @@ cdef class Entity(object): The string representation of the indexing sets for this entity or an empty array if the entity is scalar. """ + cdef size_t i cdef size_t size cdef char** sets cdef list pylist = [] @@ -188,6 +193,9 @@ cdef class Entity(object): pylist.append(sets[i].decode('utf-8')) else: pylist.append(None) + campl.AMPL_StringFree(&sets[i]) + free(sets) + return pylist def xref(self): @@ -297,15 +305,18 @@ cdef class Entity(object): df = data df_c = df.get_ptr() campl.AMPL_EntitySetValues(self._c_ampl, _name_c, df_c) + campl.AMPL_StringFree(&_name_c) elif isinstance(data, dict): df = DataFrame.from_dict(data) df_c = df.get_ptr() campl.AMPL_EntitySetValues(self._c_ampl, _name_c, df_c) + campl.AMPL_StringFree(&_name_c) else: if pd is not None and isinstance(data, (pd.DataFrame, pd.Series)): df = DataFrame.from_pandas(data, indexarity=self.indexarity()) df_c = df.get_ptr() campl.AMPL_EntitySetValues(self._c_ampl, _name_c, df_c) + campl.AMPL_StringFree(&_name_c) return raise TypeError(f"Unexpected data type: {type(data)}.") diff --git a/amplpy/parameter.pxi b/amplpy/parameter.pxi index acccb9b..88d7a94 100644 --- a/amplpy/parameter.pxi +++ b/amplpy/parameter.pxi @@ -79,7 +79,10 @@ cdef class Parameter(Entity): cdef campl.AMPL_VARIANT* v campl.AMPL_InstanceGetName(self._c_ampl, self._name.encode('utf-8'), tuple_c, &expression) campl.AMPL_GetValue(self._c_ampl, expression, &v) - return to_py_variant(v) + campl.AMPL_StringFree(&expression) + py_variant = to_py_variant(v) + campl.AMPL_VariantFree(&v) + return py_variant def value(self): """ @@ -87,7 +90,9 @@ cdef class Parameter(Entity): """ cdef campl.AMPL_VARIANT* v campl.AMPL_GetValue(self._c_ampl, self._name.encode('utf-8'), &v) - return to_py_variant(v) + py_variant = to_py_variant(v) + campl.AMPL_VariantFree(&v) + return py_variant def set(self, *args): """ diff --git a/amplpy/util.pxi b/amplpy/util.pxi index 744d7bf..44d239a 100644 --- a/amplpy/util.pxi +++ b/amplpy/util.pxi @@ -180,11 +180,13 @@ cdef void setValuesPyDict(campl.AMPL* ampl, str name, dicts): for i, (key, value) in enumerate(dicts.items()): key_c = to_c_tuple(key) campl.AMPL_ParameterInstanceSetStringValue(ampl, name.encode('utf-8'), key_c, value.encode('utf-8')) + campl.AMPL_TupleFree(&key_c) elif has_numbers and not has_strings: for i, (key, value) in enumerate(dicts.items()): if isinstance(value, int) or isinstance(value, float): key_c = to_c_tuple(key) - campl.AMPL_ParameterInstanceSetNumericValue(ampl, name.encode('utf-8'), key_c, value) + campl.AMPL_ParameterInstanceSetNumericValue(ampl, name.encode('utf-8'), key_c, value) + campl.AMPL_TupleFree(&key_c) else: raise ValueError("Unexpected value type") else: