Wed 27 Sep 2017 05:27:48 PM UTC, comment #2:
What I meant when I was talking about commenting out code was to comment out the entire cdef_manager::initialize() method (from line 3360 to line 3658 inclusive). This removes all leaks, at least on my system.
I added the code snippet to only show where a recursion occurs. I commented some code out of the snippet to make it more readable (I wanted the most important code to be visible).
To describe the recursion in other terms, using the code as is, after line 3368 the tmp_meta_class.rep->refcount is 5:
- tmp_meta_class
- tmp_meta_class.get_rep()->klass (or in other words: (dynamic_cast<cdef_object_base *>(tmp_meta_class.rep))->klass )
- tmp_handle.get_rep()->klass (or in other words: (dynamic_cast<cdef_object_base *>(tmp_handle.rep))->klass )
- m_meta_class
- entry in cdef_manager::m_all_classes
The recursion exists between instances 1 and 2.
If all of the following:
- tmp_meta_class
- tmp_handle (or tmp_handle.get_rep()->klass)
- m_meta_class
- cdef_manager::m_all_classes
get destroyed the tmp_meta_class.rep->refcount will still be 1 (even though tmp_meta_class itself does not exist).
|
Tue 26 Sep 2017 10:46:39 PM UTC, original submission:
I have been getting a large printout memory leak every time I would run Octave with the addresss sanitizer. The printout would look more or less like this:
With a summary of about 180K bytes leaked. I haven't seen a bug report for this issue so I'm submitting it.
I have been able to narrow it down to cdef_manager::initialize() as the problem (I reached this conclusion by commenting out the entire function).
I believe what is happening is this (from cdef_manager::initialize() ):
When calling cdef_class.set_class() basically creates a recursive loop that disallows tmp_meta_class.rep to be destroyed.
It has been helpful for me to look at the inheritance diagrams for cdef_object and cdef_object_rep to not get lost in all of the different C++ classes.
This loop looks like this:
tmp_meta_class.rep == tmp_meta_class.get_class ().rep
For more explanation cdef_class::get_class() returns the property cdef_class cdef_object_base::klass property which holds "The class of the object" (from the source comment).
Which means that when there's only 1 tmp_meta_class.rep left the tmp_meta_class.rep->refcount == 2. And the only way to destroy tmp_meta_class.rep is to first destroy the cdef_object_base::klass.
|