Skip to content

Struct members of cdef'd classes don't get destroyed #3226

Closed
@david-cortes

Description

@david-cortes

If I create a cdef'd class in a cython file having a struct as class member, and then instantiate that class in python, the structs do not get destroyed when the python object is deleted. Adding an explicit call to the struct destructor in __dealloc__ will do the job however.

Example:
cppheader.hpp:

#include <vector>

typedef struct MyObject {
	int val;
	std::vector<double> big_obj;
} MyObject;

typedef struct InfoHolder {
	std::vector<MyObject> v;
	int some_val;
} InfoHolder;

void increase_size(MyObject &my_obj)
{
	my_obj.big_obj.resize(10000000, 1);
}

void force_destroy(InfoHolder &info_holder)
{
	info_holder.~InfoHolder();
}

cyfile.pyx:

from libcpp.vector cimport vector

cdef extern from "cppheader.hpp":
	ctypedef struct MyObject:
		int val
		vector[double] big_obj
	ctypedef struct InfoHolder:
		vector[MyObject] v
		int some_val
	void increase_size(MyObject &my_obj)
	void force_destroy(InfoHolder &info_holder)

cdef class PyInfoHolder:
	cdef InfoHolder info_holder
	def __init__(self):
		self.info_holder.v.resize(1);
		increase_size(self.info_holder.v.at(0))	
	def say_hello(self):
		print("hello")

pyfile.py:

from cyfile import PyInfoHolder

for i in range(100):
	py_obj = PyInfoHolder()
	py_obj.say_hello()
print("end")

Watch the memory usage when running python pyfile.py, and then compare against the following alternative cython class:

cdef class PyInfoHolder:
	cdef InfoHolder info_holder
	def __init__(self):
		self.info_holder.v.resize(1);
		increase_size(self.info_holder.v.at(0))
	def __dealloc__(self):
		force_destroy(self.info_holder)		
	def say_hello(self):
		print("hello")

(For some reason, the structs also cannot call their destructor explicitly within cython - e.g. self.info_holder.~InfoHolder() fails to compile)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions