Chris_G wrote: ↑Fri Apr 09, 2021 5:18 pm
Thanks.
How did you find this bug ?
It was just a test by disabling the define ATTR_TRACKING in PyObjectBase.cpp. If it's off then some parts of the code in __getattro and __setattro are not active that does some tracking.
Additionally, I have a special build where the address sanitizer compiler switch is enabled and this reports a list of function calls that doesn't free allocated memory when exiting FreeCAD. So, I dumped the output to a file when ATTR_TRACKING is active and to another file when it's inactive.
The difference between the two files gives me the affected functions.
I did search in Draft's get_svg() because I thought the leak was happening there.
I didn't think it was down in the C++ code.
What does setNotTracking() do ?
In most of our C++ classes that return a Python object they pass a copy of the wrapped object because passing a reference or pointer is cumbersome and can easily lead to hard to find segmentation faults. But the consequence is that code like this:
has no effect because the change is applied to a tmp. object.
Thus, in the past when changing the placement we had to write code like this:
Code: Select all
placement = obj.Placement
base = placement.Base
base.x = 10.0
placement.Base = base
obj.Placement = placement
that is very unpythonic. Now, in order to support the direct way I implemented the tracking possibility so that when changing the x attribute it notifies the Base attribute that notifies the Placement attribute and this notifies the feature object.
However, there are cases where an attribute is considered read-only (like shape.Vertexes[0].Point) and this then doesn't need to be in the list of tracked objects. In this case e..g the Point attribute is read-only and it's not possible to modify the coordinates of the Vertex but it was still tracked. The result is that there is a cyclic dependency where the reference counter of both objects are incremented and the garbage collector has no chance to find it and thus cannot destroy the Python objects.
Does it prevent refcount increase of the py object ?
Yes.