PyAPI_FUNC(void) _Py_ForgetReference(PyObject *);
PyAPI_FUNC(void) _Py_Dealloc(PyObject *);
PyAPI_FUNC(void) _Py_PrintReferences(FILE *);
+PyAPI_FUNC(void) _Py_PrintReferenceAddresses(FILE *);
PyAPI_FUNC(void) _Py_AddToAllObjects(PyObject *, int force);
#else
(*dealloc)(op);
}
+/* Print all live objects. Because PyObject_Print is called, the
+ * interpreter must be in a healthy state.
+ */
void
_Py_PrintReferences(FILE *fp)
{
PyObject *op;
fprintf(fp, "Remaining objects:\n");
for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
- fprintf(fp, "[%d] ", op->ob_refcnt);
+ fprintf(fp, "%p [%d] ", op, op->ob_refcnt);
if (PyObject_Print(op, fp, 0) != 0)
PyErr_Clear();
putc('\n', fp);
}
}
+/* Print the addresses of all live objects. Unlike _Py_PrintReferences, this
+ * doesn't make any calls to the Python C API, so is always safe to call.
+ */
+void
+_Py_PrintReferenceAddresses(FILE *fp)
+{
+ PyObject *op;
+ fprintf(fp, "Remaining object addresses:\n");
+ for (op = refchain._ob_next; op != &refchain; op = op->_ob_next)
+ fprintf(fp, "%p [%d]\n", op, op->ob_refcnt);
+}
+
PyObject *
_Py_GetObjects(PyObject *self, PyObject *args)
{
* Alas, a lot of stuff may still be alive now that will be cleaned
* up later.
*/
- if (Py_GETENV("PYTHONDUMPREFS")) {
+ if (Py_GETENV("PYTHONDUMPREFS"))
_Py_PrintReferences(stderr);
- }
#endif /* Py_TRACE_REFS */
/* Now we decref the exception classes. After this point nothing
PyGrammar_RemoveAccelerators(&_PyParser_Grammar);
+#ifdef Py_TRACE_REFS
+ /* Display addresses (& refcnts) of all objects still alive.
+ * An address can be used to find the repr of the object, printed
+ * above by _Py_PrintReferences.
+ */
+ if (Py_GETENV("PYTHONDUMPREFS"))
+ _Py_PrintReferenceAddresses(stderr);
+#endif /* Py_TRACE_REFS */
#ifdef PYMALLOC_DEBUG
if (Py_GETENV("PYTHONMALLOCSTATS"))
_PyObject_DebugMallocStats();