@@ -1161,6 +1161,25 @@ py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
11611161 return get_traces .list ;
11621162}
11631163
1164+ static traceback_t *
1165+ tracemalloc_get_traceback (const void * ptr )
1166+ {
1167+ trace_t trace ;
1168+ int found ;
1169+
1170+ if (!tracemalloc_config .tracing )
1171+ return NULL ;
1172+
1173+ TABLES_LOCK ();
1174+ found = _Py_HASHTABLE_GET (tracemalloc_traces , ptr , trace );
1175+ TABLES_UNLOCK ();
1176+
1177+ if (!found )
1178+ return NULL ;
1179+
1180+ return trace .traceback ;
1181+ }
1182+
11641183PyDoc_STRVAR (tracemalloc_get_object_traceback_doc ,
11651184 "_get_object_traceback(obj)\n"
11661185 "\n"
@@ -1175,28 +1194,54 @@ py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
11751194{
11761195 PyTypeObject * type ;
11771196 void * ptr ;
1178- trace_t trace ;
1179- int found ;
1180-
1181- if (!tracemalloc_config .tracing )
1182- Py_RETURN_NONE ;
1197+ traceback_t * traceback ;
11831198
11841199 type = Py_TYPE (obj );
11851200 if (PyType_IS_GC (type ))
11861201 ptr = (void * )((char * )obj - sizeof (PyGC_Head ));
11871202 else
11881203 ptr = (void * )obj ;
11891204
1190- TABLES_LOCK ();
1191- found = _Py_HASHTABLE_GET (tracemalloc_traces , ptr , trace );
1192- TABLES_UNLOCK ();
1193-
1194- if (!found )
1205+ traceback = tracemalloc_get_traceback (ptr );
1206+ if (traceback == NULL )
11951207 Py_RETURN_NONE ;
11961208
1197- return traceback_to_pyobject (trace .traceback , NULL );
1209+ return traceback_to_pyobject (traceback , NULL );
1210+ }
1211+
1212+ #define PUTS (fd , str ) _Py_write_noraise(fd, str, (int)strlen(str))
1213+
1214+ static void
1215+ _PyMem_DumpFrame (int fd , frame_t * frame )
1216+ {
1217+ PUTS (fd , " File \"" );
1218+ _Py_DumpASCII (fd , frame -> filename );
1219+ PUTS (fd , "\", line " );
1220+ _Py_DumpDecimal (fd , frame -> lineno );
1221+ PUTS (fd , "\n" );
11981222}
11991223
1224+ /* Dump the traceback where a memory block was allocated into file descriptor
1225+ fd. The function may block on TABLES_LOCK() but it is unlikely. */
1226+ void
1227+ _PyMem_DumpTraceback (int fd , const void * ptr )
1228+ {
1229+ traceback_t * traceback ;
1230+ int i ;
1231+
1232+ traceback = tracemalloc_get_traceback (ptr );
1233+ if (traceback == NULL )
1234+ return ;
1235+
1236+ PUTS (fd , "Memory block allocated at (most recent call first):\n" );
1237+ for (i = 0 ; i < traceback -> nframe ; i ++ ) {
1238+ _PyMem_DumpFrame (fd , & traceback -> frames [i ]);
1239+ }
1240+ PUTS (fd , "\n" );
1241+ }
1242+
1243+ #undef PUTS
1244+
12001245PyDoc_STRVAR (tracemalloc_start_doc ,
12011246 "start(nframe: int=1)\n"
12021247 "\n"
0 commit comments