Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 406fe3b

Browse files
committed
Repaired the debug Windows deaths in test_descr, by allocating enough
pad memory to properly align the __dict__ pointer in all cases. gcmodule.c/objimpl.h, _PyObject_GC_Malloc: + Added a "padding" argument so that this flavor of malloc can allocate enough bytes for alignment padding (it can't know this is needed, but its callers do). typeobject.c, PyType_GenericAlloc: + Allocated enough bytes to align the __dict__ pointer. + Sped and simplified the round-up-to-PTRSIZE logic. + Added blank lines so I could parse the if/else blocks <0.7 wink>.
1 parent 7254e5a commit 406fe3b

3 files changed

Lines changed: 33 additions & 21 deletions

File tree

Include/objimpl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ extern DL_IMPORT(void) _PyObject_Del(PyObject *);
230230
#define PyObject_IS_GC(o) (PyType_IS_GC((o)->ob_type) && \
231231
((o)->ob_type->tp_is_gc == NULL || (o)->ob_type->tp_is_gc(o)))
232232

233-
extern DL_IMPORT(PyObject *) _PyObject_GC_Malloc(PyTypeObject *, int);
233+
extern DL_IMPORT(PyObject *) _PyObject_GC_Malloc(PyTypeObject *,
234+
int nitems, size_t padding);
234235
extern DL_IMPORT(PyVarObject *) _PyObject_GC_Resize(PyVarObject *, int);
235236

236237
#define PyObject_GC_Resize(type, op, n) \

Modules/gcmodule.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -798,13 +798,14 @@ _PyObject_GC_UnTrack(PyObject *op)
798798
}
799799

800800
PyObject *
801-
_PyObject_GC_Malloc(PyTypeObject *tp, int size)
801+
_PyObject_GC_Malloc(PyTypeObject *tp, int nitems, size_t padding)
802802
{
803803
PyObject *op;
804804
#ifdef WITH_CYCLE_GC
805-
const size_t nbytes = sizeof(PyGC_Head) +
806-
(size_t)_PyObject_VAR_SIZE(tp, size);
807-
PyGC_Head *g = PyObject_MALLOC(nbytes);
805+
const size_t basic = (size_t)_PyObject_VAR_SIZE(tp, nitems);
806+
const size_t nbytes = sizeof(PyGC_Head) + basic + padding;
807+
808+
PyGC_Head *g = PyObject_MALLOC(nbytes);
808809
if (g == NULL)
809810
return (PyObject *)PyErr_NoMemory();
810811
g->gc_next = NULL;
@@ -820,7 +821,7 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int size)
820821
}
821822
op = FROM_GC(g);
822823
#else
823-
op = PyObject_MALLOC(_PyObject_VAR_SIZE(tp, size));
824+
op = PyObject_MALLOC(_PyObject_VAR_SIZE(tp, nitems) + padding);
824825
if (op == NULL)
825826
return (PyObject *)PyErr_NoMemory();
826827

@@ -831,14 +832,14 @@ _PyObject_GC_Malloc(PyTypeObject *tp, int size)
831832
PyObject *
832833
_PyObject_GC_New(PyTypeObject *tp)
833834
{
834-
PyObject *op = _PyObject_GC_Malloc(tp, 0);
835+
PyObject *op = _PyObject_GC_Malloc(tp, 0, 0);
835836
return PyObject_INIT(op, tp);
836837
}
837838

838839
PyVarObject *
839840
_PyObject_GC_NewVar(PyTypeObject *tp, int size)
840841
{
841-
PyVarObject *op = (PyVarObject *) _PyObject_GC_Malloc(tp, size);
842+
PyVarObject *op = (PyVarObject *) _PyObject_GC_Malloc(tp, size, 0);
842843
return PyObject_INIT_VAR(op, tp, size);
843844
}
844845

Objects/typeobject.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -192,32 +192,42 @@ PyType_GenericAlloc(PyTypeObject *type, int nitems)
192192
{
193193
#define PTRSIZE (sizeof(PyObject *))
194194

195-
int size;
195+
size_t size = (size_t)_PyObject_VAR_SIZE(type, nitems);
196+
size_t padding = 0;
196197
PyObject *obj;
197198

198-
/* Inline PyObject_New() so we can zero the memory */
199-
size = _PyObject_VAR_SIZE(type, nitems);
200-
/* Round up size, if necessary, so we fully zero out __dict__ */
201-
if (type->tp_itemsize % PTRSIZE != 0) {
202-
size += PTRSIZE - 1;
203-
size /= PTRSIZE;
204-
size *= PTRSIZE;
205-
}
206-
if (PyType_IS_GC(type)) {
207-
obj = _PyObject_GC_Malloc(type, nitems);
199+
/* Round up size, if necessary, so that the __dict__ pointer
200+
following the variable part is properly aligned for the platform.
201+
This is needed only for types with a vrbl number of items
202+
before the __dict__ pointer == types that record the dict offset
203+
as a negative offset from the end of the object. If tp_dictoffset
204+
is 0, there is no __dict__; if positive, tp_dict was declared in a C
205+
struct so the compiler already took care of aligning it. */
206+
if (type->tp_dictoffset < 0) {
207+
padding = PTRSIZE - size % PTRSIZE;
208+
if (padding == PTRSIZE)
209+
padding = 0;
210+
size += padding;
208211
}
209-
else {
212+
213+
if (PyType_IS_GC(type))
214+
obj = _PyObject_GC_Malloc(type, nitems, padding);
215+
else
210216
obj = PyObject_MALLOC(size);
211-
}
217+
212218
if (obj == NULL)
213219
return PyErr_NoMemory();
220+
214221
memset(obj, '\0', size);
222+
215223
if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
216224
Py_INCREF(type);
225+
217226
if (type->tp_itemsize == 0)
218227
PyObject_INIT(obj, type);
219228
else
220229
(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);
230+
221231
if (PyType_IS_GC(type))
222232
_PyObject_GC_TRACK(obj);
223233
return obj;

0 commit comments

Comments
 (0)