diff -r 795d90c7820d Doc/c-api/memory.rst --- a/Doc/c-api/memory.rst Tue Apr 15 20:38:28 2014 +0200 +++ b/Doc/c-api/memory.rst Tue Apr 15 17:24:13 2014 -0400 @@ -92,8 +92,8 @@ functions are thread-safe, the :term:`GI need to be held. The default raw memory block allocator uses the following functions: -:c:func:`malloc`, :c:func:`realloc` and :c:func:`free`; call ``malloc(1)`` when -requesting zero bytes. +:c:func:`malloc`, :c:func:`calloc`, :c:func:`realloc` and :c:func:`free`; call +``malloc(1)`` (or ``calloc(1)``) when requesting zero bytes. .. versionadded:: 3.4 @@ -106,6 +106,12 @@ requesting zero bytes. been initialized in any way. +.. c:function:: void* PyMem_RawCalloc(size_t n) + + Similar to :c:func:`PyMem_RawMalloc` but initialize the newly allocated + memory block to zeros. + + .. c:function:: void* PyMem_RawRealloc(void *p, size_t n) Resizes the memory block pointed to by *p* to *n* bytes. The contents will @@ -136,8 +142,8 @@ behavior when requesting zero bytes, are memory from the Python heap. The default memory block allocator uses the following functions: -:c:func:`malloc`, :c:func:`realloc` and :c:func:`free`; call ``malloc(1)`` when -requesting zero bytes. +:c:func:`malloc`, :c:func:`calloc`, :c:func:`realloc` and :c:func:`free`; call +``malloc(1)`` (or ``calloc(1)``) when requesting zero bytes. .. warning:: @@ -152,6 +158,12 @@ requesting zero bytes. been called instead. The memory will not have been initialized in any way. +.. c:function:: void* PyMem_Calloc(size_t n) + + Similar to :c:func:`PyMem_Malloc` but initialize the newly allocated + memory block to zeros. + + .. c:function:: void* PyMem_Realloc(void *p, size_t n) Resizes the memory block pointed to by *p* to *n* bytes. The contents will be @@ -222,6 +234,9 @@ Customize Memory Allocators +----------------------------------------------------------+---------------------------------------+ | ``void* malloc(void *ctx, size_t size)`` | allocate a memory block | +----------------------------------------------------------+---------------------------------------+ + | ``void* calloc(void *ctx, size_t size)`` | allocate a memory block initialized | + | | with zeros | + +----------------------------------------------------------+---------------------------------------+ | ``void* realloc(void *ctx, void *ptr, size_t new_size)`` | allocate or resize a memory block | +----------------------------------------------------------+---------------------------------------+ | ``void free(void *ctx, void *ptr)`` | free a memory block | diff -r 795d90c7820d Include/objimpl.h --- a/Include/objimpl.h Tue Apr 15 20:38:28 2014 +0200 +++ b/Include/objimpl.h Tue Apr 15 17:24:13 2014 -0400 @@ -95,6 +95,7 @@ PyObject_{New, NewVar, Del}. the raw memory. */ PyAPI_FUNC(void *) PyObject_Malloc(size_t size); +PyAPI_FUNC(void *) PyObject_Calloc(size_t size); PyAPI_FUNC(void *) PyObject_Realloc(void *ptr, size_t new_size); PyAPI_FUNC(void) PyObject_Free(void *ptr); @@ -322,6 +323,7 @@ extern PyGC_Head *_PyGC_generation0; #endif /* Py_LIMITED_API */ PyAPI_FUNC(PyObject *) _PyObject_GC_Malloc(size_t); +PyAPI_FUNC(PyObject *) _PyObject_GC_Calloc(size_t); PyAPI_FUNC(PyObject *) _PyObject_GC_New(PyTypeObject *); PyAPI_FUNC(PyVarObject *) _PyObject_GC_NewVar(PyTypeObject *, Py_ssize_t); PyAPI_FUNC(void) PyObject_GC_Track(void *); diff -r 795d90c7820d Include/pymem.h --- a/Include/pymem.h Tue Apr 15 20:38:28 2014 +0200 +++ b/Include/pymem.h Tue Apr 15 17:24:13 2014 -0400 @@ -13,6 +13,7 @@ extern "C" { #ifndef Py_LIMITED_API PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size); +PyAPI_FUNC(void *) PyMem_RawCalloc(size_t size); PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size); PyAPI_FUNC(void) PyMem_RawFree(void *ptr); #endif @@ -57,6 +58,7 @@ PyAPI_FUNC(void) PyMem_RawFree(void *ptr */ PyAPI_FUNC(void *) PyMem_Malloc(size_t size); +PyAPI_FUNC(void *) PyMem_Calloc(size_t size); PyAPI_FUNC(void *) PyMem_Realloc(void *ptr, size_t new_size); PyAPI_FUNC(void) PyMem_Free(void *ptr); @@ -132,6 +134,9 @@ typedef struct { /* allocate a memory block */ void* (*malloc) (void *ctx, size_t size); + /* allocate a memory block filled by zeros */ + void* (*calloc) (void *ctx, size_t size); + /* allocate or resize a memory block */ void* (*realloc) (void *ctx, void *ptr, size_t new_size); diff -r 795d90c7820d Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c Tue Apr 15 20:38:28 2014 +0200 +++ b/Modules/_testcapimodule.c Tue Apr 15 17:24:13 2014 -0400 @@ -2710,6 +2710,20 @@ test_pymem_alloc0(PyObject *self) { void *ptr; + ptr = PyMem_RawMalloc(0); + if (ptr == NULL) { + PyErr_SetString(PyExc_RuntimeError, "PyMem_RawMalloc(0) returns NULL"); + return NULL; + } + PyMem_RawFree(ptr); + + ptr = PyMem_RawCalloc(0); + if (ptr == NULL) { + PyErr_SetString(PyExc_RuntimeError, "PyMem_RawCalloc(0) returns NULL"); + return NULL; + } + PyMem_RawFree(ptr); + ptr = PyMem_Malloc(0); if (ptr == NULL) { PyErr_SetString(PyExc_RuntimeError, "PyMem_Malloc(0) returns NULL"); @@ -2717,6 +2731,13 @@ test_pymem_alloc0(PyObject *self) } PyMem_Free(ptr); + ptr = PyMem_Calloc(0); + if (ptr == NULL) { + PyErr_SetString(PyExc_RuntimeError, "PyMem_Calloc(0) returns NULL"); + return NULL; + } + PyMem_Free(ptr); + ptr = PyObject_Malloc(0); if (ptr == NULL) { PyErr_SetString(PyExc_RuntimeError, "PyObject_Malloc(0) returns NULL"); @@ -2724,6 +2745,13 @@ test_pymem_alloc0(PyObject *self) } PyObject_Free(ptr); + ptr = PyObject_Calloc(0); + if (ptr == NULL) { + PyErr_SetString(PyExc_RuntimeError, "PyObject_Calloc(0) returns NULL"); + return NULL; + } + PyObject_Free(ptr); + Py_RETURN_NONE; } @@ -2731,6 +2759,7 @@ typedef struct { PyMemAllocator alloc; size_t malloc_size; + size_t calloc_size; void *realloc_ptr; size_t realloc_new_size; void *free_ptr; @@ -2743,6 +2772,13 @@ static void* hook_malloc (void* ctx, siz return hook->alloc.malloc(hook->alloc.ctx, size); } +static void* hook_calloc (void* ctx, size_t size) +{ + alloc_hook_t *hook = (alloc_hook_t *)ctx; + hook->calloc_size = size; + return hook->alloc.calloc(hook->alloc.ctx, size); +} + static void* hook_realloc (void* ctx, void* ptr, size_t new_size) { alloc_hook_t *hook = (alloc_hook_t *)ctx; @@ -2768,13 +2804,11 @@ test_setallocators(PyMemAllocatorDomain size_t size, size2; void *ptr, *ptr2; - hook.malloc_size = 0; - hook.realloc_ptr = NULL; - hook.realloc_new_size = 0; - hook.free_ptr = NULL; + memset(&hook, 0, sizeof(hook)); alloc.ctx = &hook; alloc.malloc = &hook_malloc; + alloc.calloc = &hook_calloc; alloc.realloc = &hook_realloc; alloc.free = &hook_free; PyMem_GetAllocator(domain, &hook.alloc); @@ -2831,6 +2865,32 @@ test_setallocators(PyMemAllocatorDomain goto fail; } + size = 99; + switch(domain) + { + case PYMEM_DOMAIN_RAW: ptr = PyMem_RawCalloc(size); break; + case PYMEM_DOMAIN_MEM: ptr = PyMem_Calloc(size); break; + case PYMEM_DOMAIN_OBJ: ptr = PyObject_Calloc(size); break; + default: ptr = NULL; break; + } + + if (ptr == NULL) { + error_msg = "calloc failed"; + goto fail; + } + + if (hook.calloc_size != size) { + error_msg = "calloc invalid size"; + goto fail; + } + + switch(domain) + { + case PYMEM_DOMAIN_RAW: PyMem_RawFree(ptr); break; + case PYMEM_DOMAIN_MEM: PyMem_Free(ptr); break; + case PYMEM_DOMAIN_OBJ: PyObject_Free(ptr); break; + } + Py_INCREF(Py_None); res = Py_None; goto finally; diff -r 795d90c7820d Modules/_tracemalloc.c --- a/Modules/_tracemalloc.c Tue Apr 15 20:38:28 2014 +0200 +++ b/Modules/_tracemalloc.c Tue Apr 15 17:24:13 2014 -0400 @@ -476,12 +476,15 @@ tracemalloc_remove_trace(void *ptr) } static void* -tracemalloc_malloc(void *ctx, size_t size) +tracemalloc_alloc(void *ctx, size_t size, int calloc) { PyMemAllocator *alloc = (PyMemAllocator *)ctx; void *ptr; - ptr = alloc->malloc(alloc->ctx, size); + if (calloc) + ptr = alloc->calloc(alloc->ctx, size); + else + ptr = alloc->malloc(alloc->ctx, size); if (ptr == NULL) return NULL; @@ -560,13 +563,16 @@ tracemalloc_free(void *ctx, void *ptr) } static void* -tracemalloc_malloc_gil(void *ctx, size_t size) +tracemalloc_alloc_gil(void *ctx, size_t size, int calloc) { void *ptr; if (get_reentrant()) { PyMemAllocator *alloc = (PyMemAllocator *)ctx; - return alloc->malloc(alloc->ctx, size); + if (calloc) + return alloc->calloc(alloc->ctx, size); + else + return alloc->malloc(alloc->ctx, size); } /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for @@ -574,13 +580,25 @@ tracemalloc_malloc_gil(void *ctx, size_t allocation twice. */ set_reentrant(1); - ptr = tracemalloc_malloc(ctx, size); + ptr = tracemalloc_alloc(ctx, size, calloc); set_reentrant(0); return ptr; } static void* +tracemalloc_malloc_gil(void *ctx, size_t size) +{ + return tracemalloc_alloc_gil(ctx, size, 0); +} + +static void* +tracemalloc_calloc_gil(void *ctx, size_t size) +{ + return tracemalloc_alloc_gil(ctx, size, 1); +} + +static void* tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size) { void *ptr2; @@ -614,7 +632,7 @@ tracemalloc_realloc_gil(void *ctx, void #ifdef TRACE_RAW_MALLOC static void* -tracemalloc_raw_malloc(void *ctx, size_t size) +tracemalloc_raw_alloc(void *ctx, size_t size, int calloc) { #ifdef WITH_THREAD PyGILState_STATE gil_state; @@ -623,7 +641,10 @@ tracemalloc_raw_malloc(void *ctx, size_t if (get_reentrant()) { PyMemAllocator *alloc = (PyMemAllocator *)ctx; - return alloc->malloc(alloc->ctx, size); + if (calloc) + return alloc->calloc(alloc->ctx, size); + else + return alloc->malloc(alloc->ctx, size); } /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc() @@ -633,10 +654,10 @@ tracemalloc_raw_malloc(void *ctx, size_t #ifdef WITH_THREAD gil_state = PyGILState_Ensure(); - ptr = tracemalloc_malloc(ctx, size); + ptr = tracemalloc_alloc(ctx, size, calloc); PyGILState_Release(gil_state); #else - ptr = tracemalloc_malloc(ctx, size); + ptr = tracemalloc_alloc(ctx, size, calloc); #endif set_reentrant(0); @@ -644,6 +665,18 @@ tracemalloc_raw_malloc(void *ctx, size_t } static void* +tracemalloc_raw_malloc(void *ctx, size_t size) +{ + return tracemalloc_raw_alloc(ctx, size, 0); +} + +static void* +tracemalloc_raw_calloc(void *ctx, size_t size) +{ + return tracemalloc_raw_alloc(ctx, size, 1); +} + +static void* tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size) { #ifdef WITH_THREAD @@ -856,6 +889,7 @@ tracemalloc_start(int max_nframe) #ifdef TRACE_RAW_MALLOC alloc.malloc = tracemalloc_raw_malloc; + alloc.calloc = tracemalloc_raw_calloc; alloc.realloc = tracemalloc_raw_realloc; alloc.free = tracemalloc_free; @@ -865,6 +899,7 @@ tracemalloc_start(int max_nframe) #endif alloc.malloc = tracemalloc_malloc_gil; + alloc.calloc = tracemalloc_calloc_gil; alloc.realloc = tracemalloc_realloc_gil; alloc.free = tracemalloc_free; diff -r 795d90c7820d Modules/gcmodule.c --- a/Modules/gcmodule.c Tue Apr 15 20:38:28 2014 +0200 +++ b/Modules/gcmodule.c Tue Apr 15 17:24:13 2014 -0400 @@ -1703,15 +1703,19 @@ PyObject_GC_UnTrack(void *op) _PyObject_GC_UNTRACK(op); } -PyObject * -_PyObject_GC_Malloc(size_t basicsize) +static PyObject * +_PyObject_GC_Alloc(size_t basicsize, int calloc) { PyObject *op; PyGC_Head *g; + size_t size; if (basicsize > PY_SSIZE_T_MAX - sizeof(PyGC_Head)) return PyErr_NoMemory(); - g = (PyGC_Head *)PyObject_MALLOC( - sizeof(PyGC_Head) + basicsize); + size = sizeof(PyGC_Head) + basicsize; + if (calloc) + g = (PyGC_Head *)PyObject_Calloc(size); + else + g = (PyGC_Head *)PyObject_Malloc(size); if (g == NULL) return PyErr_NoMemory(); g->gc.gc_refs = 0; @@ -1731,6 +1735,18 @@ PyObject * } PyObject * +_PyObject_GC_Malloc(size_t basicsize) +{ + return _PyObject_GC_Alloc(basicsize, 0); +} + +PyObject * +_PyObject_GC_Calloc(size_t basicsize) +{ + return _PyObject_GC_Alloc(basicsize, 1); +} + +PyObject * _PyObject_GC_New(PyTypeObject *tp) { PyObject *op = _PyObject_GC_Malloc(_PyObject_SIZE(tp)); diff -r 795d90c7820d Objects/obmalloc.c --- a/Objects/obmalloc.c Tue Apr 15 20:38:28 2014 +0200 +++ b/Objects/obmalloc.c Tue Apr 15 17:24:13 2014 -0400 @@ -5,6 +5,7 @@ #ifdef PYMALLOC_DEBUG /* WITH_PYMALLOC && PYMALLOC_DEBUG */ /* Forward declaration */ static void* _PyMem_DebugMalloc(void *ctx, size_t size); +static void* _PyMem_DebugCalloc(void *ctx, size_t size); static void _PyMem_DebugFree(void *ctx, void *p); static void* _PyMem_DebugRealloc(void *ctx, void *ptr, size_t size); @@ -43,6 +44,7 @@ static void _PyMem_DebugCheckAddress(cha /* Forward declaration */ static void* _PyObject_Malloc(void *ctx, size_t size); +static void* _PyObject_Calloc(void *ctx, size_t size); static void _PyObject_Free(void *ctx, void *p); static void* _PyObject_Realloc(void *ctx, void *ptr, size_t size); #endif @@ -51,7 +53,7 @@ static void* _PyObject_Realloc(void *ctx static void * _PyMem_RawMalloc(void *ctx, size_t size) { - /* PyMem_Malloc(0) means malloc(1). Some systems would return NULL + /* PyMem_RawMalloc(0) means malloc(1). Some systems would return NULL for malloc(0), which would be treated as an error. Some platforms would return a pointer with no memory behind it, which would break pymalloc. To solve these problems, allocate an extra byte. */ @@ -61,6 +63,18 @@ static void * } static void * +_PyMem_RawCalloc(void *ctx, size_t size) +{ + /* PyMem_RawCalloc(0) means calloc(1). Some systems would return NULL + for calloc(0), which would be treated as an error. Some platforms would + return a pointer with no memory behind it, which would break pymalloc. + To solve these problems, allocate an extra byte. */ + if (size == 0) + size = 1; + return calloc(1, size); +} + +static void * _PyMem_RawRealloc(void *ctx, void *ptr, size_t size) { if (size == 0) @@ -123,9 +137,9 @@ static void #endif -#define PYRAW_FUNCS _PyMem_RawMalloc, _PyMem_RawRealloc, _PyMem_RawFree +#define PYRAW_FUNCS _PyMem_RawMalloc, _PyMem_RawCalloc, _PyMem_RawRealloc, _PyMem_RawFree #ifdef WITH_PYMALLOC -# define PYOBJ_FUNCS _PyObject_Malloc, _PyObject_Realloc, _PyObject_Free +# define PYOBJ_FUNCS _PyObject_Malloc, _PyObject_Calloc, _PyObject_Realloc, _PyObject_Free #else # define PYOBJ_FUNCS PYRAW_FUNCS #endif @@ -147,7 +161,7 @@ static struct { {'o', {NULL, PYOBJ_FUNCS}} }; -#define PYDBG_FUNCS _PyMem_DebugMalloc, _PyMem_DebugRealloc, _PyMem_DebugFree +#define PYDBG_FUNCS _PyMem_DebugMalloc, _PyMem_DebugCalloc, _PyMem_DebugRealloc, _PyMem_DebugFree #endif static PyMemAllocator _PyMem_Raw = { @@ -196,6 +210,7 @@ PyMem_SetupDebugHooks(void) PyMemAllocator alloc; alloc.malloc = _PyMem_DebugMalloc; + alloc.calloc = _PyMem_DebugCalloc; alloc.realloc = _PyMem_DebugRealloc; alloc.free = _PyMem_DebugFree; @@ -228,11 +243,8 @@ PyMem_GetAllocator(PyMemAllocatorDomain case PYMEM_DOMAIN_MEM: *allocator = _PyMem; break; case PYMEM_DOMAIN_OBJ: *allocator = _PyObject; break; default: - /* unknown domain */ - allocator->ctx = NULL; - allocator->malloc = NULL; - allocator->realloc = NULL; - allocator->free = NULL; + /* unknown domain: set all attributes to NULL */ + memset(allocator, 0, sizeof(*allocator)); } } @@ -276,6 +288,16 @@ PyMem_RawMalloc(size_t size) return _PyMem_Raw.malloc(_PyMem_Raw.ctx, size); } +void * +PyMem_RawCalloc(size_t size) +{ + /* see PyMem_RawMalloc() */ + if (size > (size_t)PY_SSIZE_T_MAX) + return NULL; + + return _PyMem_Raw.calloc(_PyMem_Raw.ctx, size); +} + void* PyMem_RawRealloc(void *ptr, size_t new_size) { @@ -300,6 +322,15 @@ PyMem_Malloc(size_t size) } void * +PyMem_Calloc(size_t size) +{ + /* see PyMem_RawMalloc() */ + if (size > (size_t)PY_SSIZE_T_MAX) + return NULL; + return _PyMem.calloc(_PyMem.ctx, size); +} + +void * PyMem_Realloc(void *ptr, size_t new_size) { /* see PyMem_RawMalloc() */ @@ -352,6 +383,15 @@ PyObject_Malloc(size_t size) } void * +PyObject_Calloc(size_t size) +{ + /* see PyMem_RawCalloc() */ + if (size > (size_t)PY_SSIZE_T_MAX) + return NULL; + return _PyObject.calloc(_PyObject.ctx, size); +} + +void * PyObject_Realloc(void *ptr, size_t new_size) { /* see PyMem_RawMalloc() */ @@ -1122,7 +1162,7 @@ int Py_ADDRESS_IN_RANGE(void *P, poolp p */ static void * -_PyObject_Malloc(void *ctx, size_t nbytes) +_PyObject_Alloc(void *ctx, size_t nbytes, int calloc) { block *bp; poolp pool; @@ -1158,6 +1198,8 @@ static void * assert(bp != NULL); if ((pool->freeblock = *(block **)bp) != NULL) { UNLOCK(); + if (calloc) + memset(bp, 0, nbytes); return (void *)bp; } /* @@ -1170,6 +1212,8 @@ static void * pool->nextoffset += INDEX2SIZE(size); *(block **)(pool->freeblock) = NULL; UNLOCK(); + if (calloc) + memset(bp, 0, nbytes); return (void *)bp; } /* Pool is full, unlink from used pools. */ @@ -1178,6 +1222,8 @@ static void * next->prevpool = pool; pool->nextpool = next; UNLOCK(); + if (calloc) + memset(bp, 0, nbytes); return (void *)bp; } @@ -1257,6 +1303,8 @@ static void * assert(bp != NULL); pool->freeblock = *(block **)bp; UNLOCK(); + if (calloc) + memset(bp, 0, nbytes); return (void *)bp; } /* @@ -1272,6 +1320,8 @@ static void * pool->freeblock = bp + size; *(block **)(pool->freeblock) = NULL; UNLOCK(); + if (calloc) + memset(bp, 0, nbytes); return (void *)bp; } @@ -1311,13 +1361,29 @@ redirect: * has been reached. */ { - void *result = PyMem_RawMalloc(nbytes); + void *result; + if (calloc) + result = PyMem_RawCalloc(nbytes); + else + result = PyMem_RawMalloc(nbytes); if (!result) _Py_AllocatedBlocks--; return result; } } +static void * +_PyObject_Malloc(void *ctx, size_t nbytes) +{ + return _PyObject_Alloc(ctx, nbytes, 0); +} + +static void * +_PyObject_Calloc(void *ctx, size_t nbytes) +{ + return _PyObject_Alloc(ctx, nbytes, 1); +} + /* free */ ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS @@ -1561,7 +1627,7 @@ static void * #endif if (p == NULL) - return _PyObject_Malloc(ctx, nbytes); + return _PyObject_Alloc(ctx, nbytes, 0); #ifdef WITH_VALGRIND /* Treat running_on_valgrind == -1 the same as 0 */ @@ -1589,7 +1655,7 @@ static void * } size = nbytes; } - bp = _PyObject_Malloc(ctx, nbytes); + bp = _PyObject_Alloc(ctx, nbytes, 0); if (bp != NULL) { memcpy(bp, p, size); _PyObject_Free(ctx, p); @@ -1745,7 +1811,7 @@ p[2*S+n+S: 2*S+n+2*S] */ static void * -_PyMem_DebugMalloc(void *ctx, size_t nbytes) +_PyMem_DebugAlloc(void *ctx, size_t nbytes, int calloc) { debug_alloc_api_t *api = (debug_alloc_api_t *)ctx; uchar *p; /* base address of malloc'ed block */ @@ -1758,7 +1824,10 @@ static void * /* overflow: can't represent total as a size_t */ return NULL; - p = (uchar *)api->alloc.malloc(api->alloc.ctx, total); + if (calloc) + p = (uchar *)api->alloc.calloc(api->alloc.ctx, total); + else + p = (uchar *)api->alloc.malloc(api->alloc.ctx, total); if (p == NULL) return NULL; @@ -1767,7 +1836,7 @@ static void * p[SST] = (uchar)api->api_id; memset(p + SST + 1, FORBIDDENBYTE, SST-1); - if (nbytes > 0) + if (nbytes > 0 && !calloc) memset(p + 2*SST, CLEANBYTE, nbytes); /* at tail, write pad (SST bytes) and serialno (SST bytes) */ @@ -1778,6 +1847,18 @@ static void * return p + 2*SST; } +static void * +_PyMem_DebugMalloc(void *ctx, size_t nbytes) +{ + return _PyMem_DebugAlloc(ctx, nbytes, 0); +} + +static void * +_PyMem_DebugCalloc(void *ctx, size_t nbytes) +{ + return _PyMem_DebugAlloc(ctx, nbytes, 1); +} + /* The debug free first checks the 2*SST bytes on each end for sanity (in particular, that the FORBIDDENBYTEs with the api ID are still intact). Then fills the original bytes with DEADBYTE. @@ -1811,7 +1892,7 @@ static void * int i; if (p == NULL) - return _PyMem_DebugMalloc(ctx, nbytes); + return _PyMem_DebugAlloc(ctx, nbytes, 0); _PyMem_DebugCheckAddress(api->api_id, p); bumpserialno(); diff -r 795d90c7820d Objects/typeobject.c --- a/Objects/typeobject.c Tue Apr 15 20:38:28 2014 +0200 +++ b/Objects/typeobject.c Tue Apr 15 17:24:13 2014 -0400 @@ -884,15 +884,13 @@ PyType_GenericAlloc(PyTypeObject *type, /* note that we need to add one, for the sentinel */ if (PyType_IS_GC(type)) - obj = _PyObject_GC_Malloc(size); + obj = _PyObject_GC_Calloc(size); else - obj = (PyObject *)PyObject_MALLOC(size); + obj = (PyObject *)PyObject_Calloc(size); if (obj == NULL) return PyErr_NoMemory(); - memset(obj, '\0', size); - if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) Py_INCREF(type);