@@ -410,34 +410,66 @@ _Py_BreakPoint(void)
410
410
}
411
411
412
412
413
+ /* Heuristic checking if the object memory has been deallocated.
414
+ Rely on the debug hooks on Python memory allocators which fills the memory
415
+ with DEADBYTE (0xDB) when memory is deallocated.
416
+
417
+ The function can be used to prevent segmentation fault on dereferencing
418
+ pointers like 0xdbdbdbdbdbdbdbdb. Such pointer is very unlikely to be mapped
419
+ in memory. */
420
+ int
421
+ _PyObject_IsFreed (PyObject * op )
422
+ {
423
+ int freed = _PyMem_IsFreed (& op -> ob_type , sizeof (op -> ob_type ));
424
+ /* ignore op->ob_ref: the value can have be modified
425
+ by Py_INCREF() and Py_DECREF(). */
426
+ #ifdef Py_TRACE_REFS
427
+ freed &= _PyMem_IsFreed (& op -> _ob_next , sizeof (op -> _ob_next ));
428
+ freed &= _PyMem_IsFreed (& op -> _ob_prev , sizeof (op -> _ob_prev ));
429
+ #endif
430
+ return freed ;
431
+ }
432
+
433
+
413
434
/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */
414
435
void
415
436
_PyObject_Dump (PyObject * op )
416
437
{
417
- if (op == NULL )
418
- fprintf (stderr , "NULL\n" );
419
- else {
420
- PyGILState_STATE gil ;
421
- PyObject * error_type , * error_value , * error_traceback ;
422
-
423
- fprintf (stderr , "object : " );
424
- gil = PyGILState_Ensure ();
425
-
426
- PyErr_Fetch (& error_type , & error_value , & error_traceback );
427
- (void )PyObject_Print (op , stderr , 0 );
428
- PyErr_Restore (error_type , error_value , error_traceback );
429
-
430
- PyGILState_Release (gil );
431
- /* XXX(twouters) cast refcount to long until %zd is
432
- universally available */
433
- fprintf (stderr , "\n"
434
- "type : %s\n"
435
- "refcount: %ld\n"
436
- "address : %p\n" ,
437
- Py_TYPE (op )== NULL ? "NULL" : Py_TYPE (op )-> tp_name ,
438
- (long )op -> ob_refcnt ,
439
- op );
438
+ if (op == NULL ) {
439
+ fprintf (stderr , "<NULL object>\n" );
440
+ fflush (stderr );
441
+ return ;
442
+ }
443
+
444
+ if (_PyObject_IsFreed (op )) {
445
+ /* It seems like the object memory has been freed:
446
+ don't access it to prevent a segmentation fault. */
447
+ fprintf (stderr , "<freed object>\n" );
440
448
}
449
+
450
+ PyGILState_STATE gil ;
451
+ PyObject * error_type , * error_value , * error_traceback ;
452
+
453
+ fprintf (stderr , "object : " );
454
+ fflush (stderr );
455
+ gil = PyGILState_Ensure ();
456
+
457
+ PyErr_Fetch (& error_type , & error_value , & error_traceback );
458
+ (void )PyObject_Print (op , stderr , 0 );
459
+ fflush (stderr );
460
+ PyErr_Restore (error_type , error_value , error_traceback );
461
+
462
+ PyGILState_Release (gil );
463
+ /* XXX(twouters) cast refcount to long until %zd is
464
+ universally available */
465
+ fprintf (stderr , "\n"
466
+ "type : %s\n"
467
+ "refcount: %ld\n"
468
+ "address : %p\n" ,
469
+ Py_TYPE (op )== NULL ? "NULL" : Py_TYPE (op )-> tp_name ,
470
+ (long )op -> ob_refcnt ,
471
+ op );
472
+ fflush (stderr );
441
473
}
442
474
443
475
PyObject *
0 commit comments