Skip to content

Commit 85e535a

Browse files
committed
significant rewrite to address review comments
1 parent 97dc30c commit 85e535a

File tree

6 files changed

+640
-377
lines changed

6 files changed

+640
-377
lines changed

Doc/c-api/allocation.rst

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ Allocating Objects on the Heap
1919
not initialized. Specifically, this function does **not** call the object's
2020
:meth:`~object.__init__` method (:c:member:`~PyTypeObject.tp_init` slot).
2121
22+
.. warning::
23+
24+
This function does not guarantee that the memory will be completely
25+
zeroed before it is initialized. Fields that are not initialized by this
26+
function will have indeterminate values, which might include sensitive
27+
data from previously destroyed objects (e.g., secret keys).
28+
2229
2330
.. c:function:: PyVarObject* PyObject_InitVar(PyVarObject *op, PyTypeObject *type, Py_ssize_t size)
2431
@@ -28,23 +35,44 @@ Allocating Objects on the Heap
2835
2936
.. c:macro:: PyObject_New(TYPE, typeobj)
3037
31-
Calls :c:func:`PyObject_Malloc` to allocate memory for a new Python object
32-
using the C structure type *TYPE* and the Python type object *typeobj*
33-
(``PyTypeObject*``), then initializes the memory like
38+
Allocates a new Python object using the C structure type *TYPE* and the
39+
Python type object *typeobj* (``PyTypeObject*``) by calling
40+
:c:func:`PyObject_Malloc` to allocate memory and initializing it like
3441
:c:func:`PyObject_Init`. The caller will own the only reference to the
3542
object (i.e. its reference count will be one). The size of the memory
3643
allocation is determined from the :c:member:`~PyTypeObject.tp_basicsize`
3744
field of the type object.
3845
39-
This does not call :c:member:`~PyTypeObject.tp_alloc`,
46+
For a type's :c:member:`~PyTypeObject.tp_alloc` slot,
47+
:c:func:`PyType_GenericAlloc` is generally preferred over a custom function
48+
that simply calls this macro.
49+
50+
This macro does not call :c:member:`~PyTypeObject.tp_alloc`,
4051
:c:member:`~PyTypeObject.tp_new` (:meth:`~object.__new__`), or
4152
:c:member:`~PyTypeObject.tp_init` (:meth:`~object.__init__`).
4253
43-
This should not be used for objects with :c:macro:`Py_TPFLAGS_HAVE_GC` set
44-
in :c:member:`~PyTypeObject.tp_flags`; use :c:macro:`PyObject_GC_New`
54+
This macro should not be used for objects with :c:macro:`Py_TPFLAGS_HAVE_GC`
55+
set in :c:member:`~PyTypeObject.tp_flags`; use :c:macro:`PyObject_GC_New`
4556
instead.
4657
47-
Memory allocated by this function must be freed with :c:func:`PyObject_Free`.
58+
Memory allocated by this function must be freed with
59+
:c:func:`PyObject_Free`.
60+
61+
.. warning::
62+
63+
The returned memory is not guaranteed to have been completely zeroed
64+
before it was initialized. Fields that were not initialized by this
65+
function will have indeterminate values, which might include sensitive
66+
data from previously destroyed objects (e.g., secret keys).
67+
68+
.. warning::
69+
70+
This macro does not construct a fully initialized object of the given
71+
type; it merely allocates memory and prepares it for further
72+
initialization by :c:member:`~PyTypeObject.tp_init`. To construct a
73+
fully initialized object, call *typeobj* instead. For example::
74+
75+
PyObject *foo = PyObject_CallNoArgs((PyObject *)&PyFoo_Type);
4876
4977
5078
.. c:macro:: PyObject_NewVar(TYPE, typeobj, size)
@@ -65,7 +93,8 @@ Allocating Objects on the Heap
6593
in :c:member:`~PyTypeObject.tp_flags`; use :c:macro:`PyObject_GC_NewVar`
6694
instead.
6795

68-
Memory allocated by this function must be freed with :c:func:`PyObject_Free`.
96+
Memory allocated by this function must be freed with
97+
:c:func:`PyObject_Free`.
6998

7099

71100
.. c:function:: void PyObject_Del(void *op)

Doc/c-api/lifecycle.dot

Lines changed: 25 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,61 +15,50 @@ digraph G {
1515
]
1616

1717
"start" [fontname="Times-Italic" shape=plain label=< start > style=invis]
18-
"tp_alloc" [href="typeobj.html#c.PyTypeObject.tp_alloc" target="_top"]
19-
"tp_new" [href="typeobj.html#c.PyTypeObject.tp_new" target="_top"]
18+
{
19+
rank="same"
20+
"tp_new" [href="typeobj.html#c.PyTypeObject.tp_new" target="_top"]
21+
"tp_alloc" [href="typeobj.html#c.PyTypeObject.tp_alloc" target="_top"]
22+
}
2023
"tp_init" [href="typeobj.html#c.PyTypeObject.tp_init" target="_top"]
2124
{
2225
rank="same"
23-
"alive" [
24-
fontname="Times-Italic"
25-
label=<alive, ref count &gt; 0>
26-
shape=box
27-
]
26+
"reachable" [fontname="Times-Italic" shape=box]
2827
"tp_traverse" [
2928
href="typeobj.html#c.PyTypeObject.tp_traverse"
30-
shape=octagon
3129
target="_top"
3230
]
3331
}
34-
"tp_finalize" [
35-
href="typeobj.html#c.PyTypeObject.tp_finalize"
36-
shape=octagon
37-
target="_top"
38-
]
39-
"tp_clear" [
40-
href="typeobj.html#c.PyTypeObject.tp_clear"
41-
shape=octagon
42-
target="_top"
43-
]
32+
"tp_finalize" [href="typeobj.html#c.PyTypeObject.tp_finalize" target="_top"]
33+
"tp_clear" [href="typeobj.html#c.PyTypeObject.tp_clear" target="_top"]
4434
"tp_dealloc" [
4535
href="typeobj.html#c.PyTypeObject.tp_dealloc"
4636
ordering="in"
4737
target="_top"
4838
]
4939
"tp_free" [href="typeobj.html#c.PyTypeObject.tp_free" target="_top"]
5040

51-
"start" -> "tp_alloc"
52-
"tp_alloc" -> "tp_new"
41+
"start" -> "tp_new"
42+
"tp_new" -> "tp_alloc" [label=< direct call >]
43+
"tp_alloc" -> "tp_new" [label=< >]
5344
"tp_new" -> "tp_init"
54-
"tp_init" -> "alive"
55-
"tp_traverse" -> "alive"
56-
"alive" -> "tp_traverse"
57-
"alive" -> "tp_clear" [label=< cyclic <br/>isolate >]
58-
"alive" -> "tp_finalize" [
59-
dir="back"
60-
label=< resurrected >
45+
"tp_init" -> "reachable"
46+
"reachable" -> "tp_traverse"
47+
"tp_traverse" -> "reachable"
48+
"reachable" -> "tp_clear" [
49+
label=< was resurrected, <br/> then became <br/> unreachable >
6150
]
62-
"alive" -> "tp_finalize" [label=< cyclic <br/>isolate >]
63-
"tp_finalize" -> "tp_clear"
51+
"reachable" -> "tp_finalize" [dir="back" label=< resurrected >]
52+
"reachable" -> "tp_finalize" [label=< became <br/> unreachable >]
53+
"tp_finalize" -> "tp_clear" [label=< still <br/> unreachable >]
6454
"tp_finalize" -> "tp_dealloc" [
6555
dir="back"
6656
href="lifecycle.html#c.PyObject_CallFinalizerFromDealloc"
6757
label=<
6858
<table border="0" cellborder="0" cellpadding="0" cellspacing="0">
6959
<tr>
70-
<td rowspan="4"> </td>
71-
<td align="left">optional call to</td>
72-
<td rowspan="4"> </td>
60+
<td rowspan="4"> </td>
61+
<td align="left">recommended call to</td>
7362
</tr>
7463
<tr>
7564
<td align="left"><font face="Courier">PyObject_Call</font></td>
@@ -82,12 +71,8 @@ digraph G {
8271
>
8372
target="_top"
8473
]
85-
"tp_finalize" -> "tp_dealloc" [label=< ref count <br/> == 0 >]
86-
"tp_clear" -> "tp_dealloc" [label=< ref count <br/> == 0 >]
87-
"tp_clear" -> "tp_dealloc" [
88-
dir="back"
89-
label=< optional<br/>direct call >
90-
]
91-
"alive" -> "tp_dealloc" [label=< ref count <br/> == 0 >]
92-
"tp_dealloc" -> "tp_free" [label=< directly calls >]
74+
"tp_finalize" -> "tp_dealloc" [label=< still <br/> unreachable >]
75+
"tp_clear" -> "tp_dealloc" [label=< >]
76+
"reachable" -> "tp_dealloc" [label=< became <br/> unreachable >]
77+
"tp_dealloc" -> "tp_free" [label=< direct call >]
9378
}

0 commit comments

Comments
 (0)