[Julien Danjou]
... Supposedly PyObject_Malloc() returns some memory space to store a PyObject. If that was true all the time, that would allow anyone to introspect the allocated memory and understand why it's being used.
Unfortunately, this is not the case. Objects whose types are tracked by the GC go through _PyObject_GC_Alloc() which changes the underlying memory structure to be (PyGC_HEAD + PyObject).
This is a bummer as there then no safe way that I can think of to know if an allocated memory space is gc-tracked or gc-untracked. It makes it therefore impossible to introspect the memory allocated by PyObject_Malloc().
I'm not clear on exactly what it is you're after, but CPython faces the same question all the time: _given_ a pointer to an object, is there, or is there not, a GC header prepended? That's answered by this C API function: """ int PyObject_IS_GC(PyObject *obj) Returns non-zero if the object implements the garbage collector protocol, otherwise returns 0. The object cannot be tracked by the garbage collector if this function returns 0. """ FYI, the implementation usually resolves it by looking at whether obj's type object has the Py_TPFLAGS_HAVE_GC flag set.