2007-04-29 09:42:17 -04:00
|
|
|
|
PEP: 3123
|
|
|
|
|
Title: Making PyObject_HEAD conform to standard C
|
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
2007-06-28 16:03:18 -04:00
|
|
|
|
Author: Martin von Löwis <martin@v.loewis.de>
|
2007-07-29 13:17:45 -04:00
|
|
|
|
Status: Final
|
2007-04-29 09:42:17 -04:00
|
|
|
|
Type: Standards Track
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 27-Apr-2007
|
|
|
|
|
Python-Version: 3.0
|
|
|
|
|
Post-History:
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
Python currently relies on undefined C behavior, with its
|
2007-07-21 05:18:45 -04:00
|
|
|
|
usage of ``PyObject_HEAD``. This PEP proposes to change that
|
2007-04-29 09:42:17 -04:00
|
|
|
|
into standard C.
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
Standard C defines that an object must be accessed only through a
|
|
|
|
|
pointer of its type, and that all other accesses are undefined
|
|
|
|
|
behavior, with a few exceptions. In particular, the following
|
|
|
|
|
code has undefined behavior::
|
|
|
|
|
|
|
|
|
|
struct FooObject{
|
|
|
|
|
PyObject_HEAD
|
|
|
|
|
int data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
PyObject *foo(struct FooObject*f){
|
|
|
|
|
return (PyObject*)f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int bar(){
|
|
|
|
|
struct FooObject *f = malloc(sizeof(struct FooObject));
|
|
|
|
|
struct PyObject *o = foo(f);
|
|
|
|
|
f->ob_refcnt = 0;
|
|
|
|
|
o->ob_refcnt = 1;
|
|
|
|
|
return f->ob_refcnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
The problem here is that the storage is both accessed as
|
2007-07-21 05:18:45 -04:00
|
|
|
|
if it where struct ``PyObject``, and as struct ``FooObject``.
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
2007-04-29 09:46:08 -04:00
|
|
|
|
Historically, compilers did not have any problems with this
|
2017-03-24 17:11:33 -04:00
|
|
|
|
code. However, modern compilers use that clause as an
|
2007-07-21 05:18:45 -04:00
|
|
|
|
optimization opportunity, finding that ``f->ob_refcnt`` and
|
|
|
|
|
``o->ob_refcnt`` cannot possibly refer to the same memory, and
|
2007-04-29 09:42:17 -04:00
|
|
|
|
that therefore the function should return 0, without having
|
|
|
|
|
to fetch the value of ob_refcnt at all in the return
|
2007-07-21 05:18:45 -04:00
|
|
|
|
statement. For GCC, Python now uses ``-fno-strict-aliasing``
|
2007-04-29 09:42:17 -04:00
|
|
|
|
to work around that problem; with other compilers, it
|
|
|
|
|
may just see undefined behavior. Even with GCC, using
|
2007-07-21 05:18:45 -04:00
|
|
|
|
``-fno-strict-aliasing`` may pessimize the generated code
|
2007-04-29 09:42:17 -04:00
|
|
|
|
unnecessarily.
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
|
=============
|
|
|
|
|
|
|
|
|
|
Standard C has one specific exception to its aliasing rules precisely
|
|
|
|
|
designed to support the case of Python: a value of a struct type may
|
|
|
|
|
also be accessed through a pointer to the first field. E.g. if a
|
2007-07-21 05:18:45 -04:00
|
|
|
|
struct starts with an ``int``, the ``struct *`` may also be cast to
|
|
|
|
|
an ``int *``, allowing to write int values into the first field.
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
2007-07-21 05:18:45 -04:00
|
|
|
|
For Python, ``PyObject_HEAD`` and ``PyObject_VAR_HEAD`` will be changed
|
2007-04-29 09:42:17 -04:00
|
|
|
|
to not list all fields anymore, but list a single field of type
|
2007-07-21 05:18:45 -04:00
|
|
|
|
``PyObject``/``PyVarObject``::
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
2007-05-23 01:30:28 -04:00
|
|
|
|
typedef struct _object {
|
2007-04-29 09:42:17 -04:00
|
|
|
|
_PyObject_HEAD_EXTRA
|
|
|
|
|
Py_ssize_t ob_refcnt;
|
|
|
|
|
struct _typeobject *ob_type;
|
2007-05-23 01:30:28 -04:00
|
|
|
|
} PyObject;
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
PyObject ob_base;
|
|
|
|
|
Py_ssize_t ob_size;
|
|
|
|
|
} PyVarObject;
|
|
|
|
|
|
|
|
|
|
#define PyObject_HEAD PyObject ob_base;
|
|
|
|
|
#define PyObject_VAR_HEAD PyVarObject ob_base;
|
|
|
|
|
|
|
|
|
|
Types defined as fixed-size structure will then include PyObject
|
2007-09-05 16:00:17 -04:00
|
|
|
|
as its first field, PyVarObject for variable-sized objects. E.g.::
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
2007-05-23 01:30:28 -04:00
|
|
|
|
typedef struct {
|
2007-04-29 09:42:17 -04:00
|
|
|
|
PyObject ob_base;
|
|
|
|
|
PyObject *start, *stop, *step;
|
|
|
|
|
} PySliceObject;
|
|
|
|
|
|
2007-07-21 05:18:45 -04:00
|
|
|
|
typedef struct {
|
2007-04-29 09:42:17 -04:00
|
|
|
|
PyVarObject ob_base;
|
|
|
|
|
PyObject **ob_item;
|
|
|
|
|
Py_ssize_t allocated;
|
|
|
|
|
} PyListObject;
|
|
|
|
|
|
2007-07-21 05:18:45 -04:00
|
|
|
|
The above definitions of ``PyObject_HEAD`` are normative, so extension
|
|
|
|
|
authors MAY either use the macro, or put the ``ob_base`` field explicitly
|
2007-04-29 09:42:17 -04:00
|
|
|
|
into their structs.
|
|
|
|
|
|
|
|
|
|
As a convention, the base field SHOULD be called ob_base. However, all
|
|
|
|
|
accesses to ob_refcnt and ob_type MUST cast the object pointer to
|
|
|
|
|
PyObject* (unless the pointer is already known to have that type), and
|
|
|
|
|
SHOULD use the respective accessor macros. To simplify access to
|
2007-05-13 10:23:03 -04:00
|
|
|
|
ob_type, ob_refcnt, and ob_size, macros::
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
2007-12-19 03:08:00 -05:00
|
|
|
|
#define Py_TYPE(o) (((PyObject*)(o))->ob_type)
|
|
|
|
|
#define Py_REFCNT(o) (((PyObject*)(o))->ob_refcnt)
|
|
|
|
|
#define Py_SIZE(o) (((PyVarObject*)(o))->ob_size)
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
2007-07-21 05:18:45 -04:00
|
|
|
|
are added. E.g. the code blocks ::
|
2007-04-29 09:46:08 -04:00
|
|
|
|
|
|
|
|
|
#define PyList_CheckExact(op) ((op)->ob_type == &PyList_Type)
|
|
|
|
|
|
|
|
|
|
return func->ob_type->tp_name;
|
|
|
|
|
|
|
|
|
|
needs to be changed to::
|
|
|
|
|
|
2007-12-19 03:08:00 -05:00
|
|
|
|
#define PyList_CheckExact(op) (Py_TYPE(op) == &PyList_Type)
|
2007-04-29 09:46:08 -04:00
|
|
|
|
|
2007-12-19 03:08:00 -05:00
|
|
|
|
return Py_TYPE(func)->tp_name;
|
2007-05-13 10:23:03 -04:00
|
|
|
|
|
2007-07-21 05:18:45 -04:00
|
|
|
|
For initialization of type objects, the current sequence ::
|
2007-05-13 10:23:03 -04:00
|
|
|
|
|
|
|
|
|
PyObject_HEAD_INIT(NULL)
|
|
|
|
|
0, /* ob_size */
|
|
|
|
|
|
2007-07-21 05:18:45 -04:00
|
|
|
|
becomes incorrect, and must be replaced with ::
|
2007-05-13 10:23:03 -04:00
|
|
|
|
|
|
|
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
|
|
|
|
Compatibility with Python 2.6
|
|
|
|
|
=============================
|
|
|
|
|
|
|
|
|
|
To support modules that compile with both Python 2.6 and Python 3.0,
|
2007-07-21 05:18:45 -04:00
|
|
|
|
the ``Py_*`` macros are added to Python 2.6. The macros ``Py_INCREF``
|
|
|
|
|
and ``Py_DECREF`` will be changed to cast their argument to ``PyObject *``,
|
|
|
|
|
so that module authors can also explicitly declare the ``ob_base``
|
2017-03-24 17:11:33 -04:00
|
|
|
|
field in modules designed for Python 2.6.
|
2007-04-29 09:42:17 -04:00
|
|
|
|
|
|
|
|
|
Copyright
|
|
|
|
|
=========
|
|
|
|
|
|
|
|
|
|
This document has been placed in the public domain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
..
|
|
|
|
|
Local Variables:
|
|
|
|
|
mode: indented-text
|
|
|
|
|
indent-tabs-mode: nil
|
|
|
|
|
sentence-end-double-space: t
|
|
|
|
|
fill-column: 70
|
|
|
|
|
coding: utf-8
|
|
|
|
|
End:
|