I am writing a C extension module for an AVL tree, and I am trying to
ensure reference counting is done correctly. I was having a problem with
the reference counting so I worked up this little POC of the problem,
and I hope someone can explain this.
Extension function :
static PyObject *_Node_test_ref_count(PyObject *self)
{
printf("\nIncrementing ref count for self - just for the hell
of it\n");
printf("\n before self has a ref count of %ld\n", Py_REFCNT(self));
Py_INCREF(self);
printf("\n after self has a ref count of %ld\n", Py_REFCNT(self));
fflush(stdout);
return self;
}
As you can see this function purely increments the reference count of
the instance.
/Note: I understand normally this would be the wrong this to do, but
this is a POC of the issue, not live code. In the live code I am
attaching a 2nd nodes to each other, and the live code therefore
increments the ref-count for both objects - so even if the Python code
deletes it's reference the reference count for the instance should still
be 1 in order to ensure it doesn't get garbage collected./
This function is exposed as the test_ref method.
This is the test case :
def test_000_009_test_ref_count(self):
node = _Node("Hello")
self.assertEqual(sys.getrefcount(node), 2)
node.test_ref()
self.assertEqual(sys.getrefcount(node), 3)
The output of this test case is :
test_000_009_test_ref_count (__main__.TestNode) ...
Incrementing ref count for self - just for the hell of it
before self has a ref count of 2
after self has a ref count of 3
FAIL
======================================================================
FAIL: test_000_009_test_ref_count (__main__.TestNode)
----------------------------------------------------------------------
Traceback (most recent call last):
File
"/home/tony/Development/python/orderedtree/tests/test_orderedtree.py",
line 62, in test_000_009_test_ref_count
self.assertEqual(sys.getrefcount(node), 3)
AssertionError: 2 != 3
So I understand why the first assert will be true - when the
sys.getrefcount() function is called the ref count is incremented
temporarily (as a borrowed reference), so there are now two references -
the 'node' variable, and the borrowed reference in the function call.
We then call the 'test_ref' method, and again that call causes a
borrowed reference (hence the ref count being 2 initially within the
method). The 'test_ref' method increments the reference of the instance
- as you can see from the output we now have a ref count of 3 - (that
count is the 'node' variable in the test case, the borrowed reference
due to the method call, and the artificial increment from the 'ref_test'
method).
When the 'ref_test' method exits I would expect the ref count of the
instance to now be 2 (one for the 'node' variable, and one as a result
of the artificial increment increment').
I would therefore expect the 2nd assertEqual in the test case to
succeed. - in this case the borrowed reference within sys.getfrefcount()
should cause the count to be 3.
As you see though that 2nd assertEqual fails - suggesting that the
refcount of 'node' is actually only 1 when the 'test_ref' method exits.
Can someone explain why the 'test_ref' method fails to change the
refcount of the 'node' instance.
--
https://mail.python.org/mailman/listinfo/python-list