diff options
-rw-r--r-- | Include/object.h | 1 | ||||
-rw-r--r-- | Objects/object.c | 17 | ||||
-rw-r--r-- | Python/pythonrun.c | 11 |
3 files changed, 26 insertions, 3 deletions
diff --git a/Include/object.h b/Include/object.h index 3ac7538..3c7264f 100644 --- a/Include/object.h +++ b/Include/object.h @@ -582,6 +582,7 @@ PyAPI_FUNC(void) _Py_NewReference(PyObject *); 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 diff --git a/Objects/object.c b/Objects/object.c index c876219..49b9839 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -2022,19 +2022,34 @@ _Py_Dealloc(PyObject *op) (*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) { diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 4cfb664..0a9a637 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -284,9 +284,8 @@ Py_Finalize(void) * 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 @@ -325,6 +324,14 @@ Py_Finalize(void) 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(); |