Index: Lib/test/test_slice.py =================================================================== --- Lib/test/test_slice.py (revision 46671) +++ Lib/test/test_slice.py (working copy) @@ -92,8 +92,29 @@ self.assertRaises(OverflowError, slice(None).indices, 1L<<100) -def test_main(): + def test_cycles_leak(self): + # This test shows results only in a debug build when + # run as a script or with the -R option to regrtest.py. + class C(object): + pass + + for i in range(10): + c = C() + s = slice(c) + c.slice = s + +def test_main(verbose=None): test_support.run_unittest(SliceTest) + # verify reference counting + if verbose and hasattr(sys, "gettotalrefcount"): + import gc + counts = [None] * 5 + for i in xrange(len(counts)): + test_support.run_unittest(SliceTest) + gc.collect() + counts[i] = sys.gettotalrefcount() + print counts + if __name__ == "__main__": - test_main() + test_main(verbose=True) Index: Objects/sliceobject.c =================================================================== --- Objects/sliceobject.c (revision 46671) +++ Objects/sliceobject.c (working copy) @@ -60,7 +60,7 @@ PyObject * PySlice_New(PyObject *start, PyObject *stop, PyObject *step) { - PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type); + PySliceObject *obj = PyObject_GC_New(PySliceObject, &PySlice_Type); if (obj == NULL) return NULL; @@ -76,6 +76,7 @@ obj->start = start; obj->stop = stop; + _PyObject_GC_TRACK(obj); return (PyObject *) obj; } @@ -217,10 +218,11 @@ static void slice_dealloc(PySliceObject *r) { - Py_DECREF(r->step); - Py_DECREF(r->start); - Py_DECREF(r->stop); - PyObject_Del(r); + _PyObject_GC_UNTRACK(r); + Py_CLEAR(r->step); + Py_CLEAR(r->start); + Py_CLEAR(r->stop); + PyObject_GC_Del(r); } static PyObject * @@ -240,6 +242,15 @@ return s; } +static int +slice_traverse(PySliceObject *r, visitproc visit, void *arg) +{ + Py_VISIT(r->step); + Py_VISIT(r->start); + Py_VISIT(r->stop); + return 0; +} + static PyMemberDef slice_members[] = { {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY}, {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY}, @@ -329,9 +340,9 @@ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ slice_doc, /* tp_doc */ - 0, /* tp_traverse */ + (traverseproc)slice_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */