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

Skip to content

Commit af3e8de

Browse files
committed
First stab at rationalizing the PyMem_ API. Mixing PyObject_xyz with
PyMem_{Del, DEL} doesn't work yet (compilation problems). pyport.h: _PyMem_EXTRA is gone. pmem.h: Repaired comments. PyMem_{Malloc, MALLOC} and PyMem_{Realloc, REALLOC} now make the same x-platform guarantees when asking for 0 bytes, and when passing a NULL pointer to the latter. object.c: PyMem_{Malloc, Realloc} just call their macro versions now, since the latter take care of the x-platform 0 and NULL stuff by themselves now. pypcre.c, grow_stack(): So sue me. On two lines, this called PyMem_RESIZE to grow a "const" area. It's not legit to realloc a const area, so the compiler warned given the new expansion of PyMem_RESIZE. It would have gotten the same warning before if it had used PyMem_Resize() instead; the older macro version, but not the function version, silently cast away the constness. IMO that was a wrong thing to do, and the docs say the macro versions of PyMem_xyz are deprecated anyway. If somebody else is resizing const areas with the macro spelling, they'll get a warning when they recompile now too.
1 parent e9e7452 commit af3e8de

4 files changed

Lines changed: 61 additions & 70 deletions

File tree

Include/pymem.h

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,77 +18,92 @@ extern "C" {
1818
Python runtime switches to its own malloc (different from standard
1919
malloc), no recompilation is required for the extensions.
2020
21-
The macro versions trade compatibility for speed. They can be used
22-
whenever there is a performance problem, but their use implies
23-
recompilation of the code for each new Python release. The Python
24-
core uses the macros because it *is* compiled on every upgrade.
25-
This might not be the case with 3rd party extensions in a custom
26-
setup (for example, a customer does not always have access to the
27-
source of 3rd party deliverables). You have been warned! */
21+
The macro versions are free to trade compatibility for speed, although
22+
there's no guarantee they're ever faster. Extensions shouldn't use the
23+
macro versions, as they don't gurantee binary compatibility across
24+
releases.
25+
26+
Do not mix calls to PyMem_xyz with calls to platform
27+
malloc/realloc/calloc/free. */
2828

2929
/*
3030
* Raw memory interface
3131
* ====================
3232
*/
3333

34-
/* To make sure the interpreter is user-malloc friendly, all memory
35-
APIs are implemented on top of this one. */
36-
3734
/* Functions */
3835

39-
/* Function wrappers around PyMem_MALLOC and friends; useful if you
40-
need to be sure that you are using the same memory allocator as
41-
Python. Note that the wrappers make sure that allocating 0 bytes
42-
returns a non-NULL pointer, even if the underlying malloc
43-
doesn't. Returned pointers must be checked for NULL explicitly.
44-
No action is performed on failure. */
36+
/* Functions supplying platform-independent semantics for malloc/realloc/
37+
free; useful if you need to be sure you're using the same memory
38+
allocator as Python (this can be especially important on Windows, if
39+
you need to make sure you're using the same MS malloc/free, and out of
40+
the same heap, as the main Python DLL uses).
41+
These functions make sure that allocating 0 bytes returns a distinct
42+
non-NULL pointer (whenever possible -- if we're flat out of memory, NULL
43+
may be returned), even if the platform malloc and realloc don't.
44+
Returned pointers must be checked for NULL explicitly. No action is
45+
performed on failure (no exception is set, no warning is printed, etc).` */
46+
4547
extern DL_IMPORT(void *) PyMem_Malloc(size_t);
4648
extern DL_IMPORT(void *) PyMem_Realloc(void *, size_t);
4749
extern DL_IMPORT(void) PyMem_Free(void *);
4850

4951
/* Starting from Python 1.6, the wrappers Py_{Malloc,Realloc,Free} are
5052
no longer supported. They used to call PyErr_NoMemory() on failure. */
5153

52-
/* Macros (override these if you want to a different malloc */
54+
/* Macros. */
5355
#ifndef PyMem_MALLOC
54-
#define PyMem_MALLOC(n) malloc(n)
55-
#define PyMem_REALLOC(p, n) realloc((void *)(p), (n))
56-
#define PyMem_FREE(p) free((void *)(p))
56+
#ifdef MALLOC_ZERO_RETURNS_NULL
57+
#define PyMem_MALLOC(n) malloc((n) ? (n) : 1)
58+
#else
59+
#define PyMem_MALLOC malloc
5760
#endif
5861

62+
/* Caution: whether MALLOC_ZERO_RETURNS_NULL is #defined has nothing to
63+
do with whether platform realloc(non-NULL, 0) normally frees the memory
64+
or returns NULL. Rather than introduce yet another config variation,
65+
just make a realloc to 0 bytes act as if to 1 instead. */
66+
#define PyMem_REALLOC(p, n) realloc((p), (n) ? (n) : 1)
67+
68+
#define PyMem_FREE free
69+
#endif /* PyMem_MALLOC */
70+
5971
/*
6072
* Type-oriented memory interface
6173
* ==============================
74+
*
75+
* These are carried along for historical reasons. There's rarely a good
76+
* reason to use them anymore.
6277
*/
6378

6479
/* Functions */
6580
#define PyMem_New(type, n) \
6681
( (type *) PyMem_Malloc((n) * sizeof(type)) )
6782
#define PyMem_Resize(p, type, n) \
6883
( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
69-
#define PyMem_Del(p) PyMem_Free(p)
84+
85+
/* In order to avoid breaking old code mixing PyObject_{New, NEW} with
86+
PyMem_{Del, DEL} (there was no choice about this in 1.5.2), the latter
87+
have to be redirected to the object allocator. */
88+
/* XXX The parser module needs rework before this can be enabled. */
89+
#if 0
90+
#define PyMem_Del PyObject_Free
91+
#else
92+
#define PyMem_Del PyMem_Free
93+
#endif
7094

7195
/* Macros */
7296
#define PyMem_NEW(type, n) \
73-
( (type *) PyMem_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) )
74-
75-
/* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */
76-
#define PyMem_RESIZE(p, type, n) \
77-
do { \
78-
size_t _sum = (n) * sizeof(type); \
79-
if (!_sum) \
80-
_sum = 1; \
81-
(p) = (type *)((p) ? \
82-
PyMem_REALLOC(p, _sum) : \
83-
PyMem_MALLOC(_sum)); \
84-
} while (0)
85-
86-
#define PyMem_DEL(p) PyMem_FREE(p)
87-
88-
/* PyMem_XDEL is deprecated. To avoid the call when p is NULL,
89-
it is recommended to write the test explicitly in the code.
90-
Note that according to ANSI C, free(NULL) has no effect. */
91-
97+
( (type *) PyMem_MALLOC((n) * sizeof(type)) )
98+
#define PyMem_RESIZE(p, type, n) \
99+
( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
100+
101+
/* XXX The parser module needs rework before this can be enabled. */
102+
#if 0
103+
#define PyMem_DEL PyObject_FREE
104+
#else
105+
#define PyMem_DEL PyMem_FREE
106+
#endif
92107

93108
#ifdef __cplusplus
94109
}

Include/pyport.h

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -384,32 +384,10 @@ extern int fsync(int fd);
384384
extern double hypot(double, double);
385385
#endif
386386

387-
388-
/************************************
389-
* MALLOC COMPATIBILITY FOR pymem.h *
390-
************************************/
391-
392387
#ifndef DL_IMPORT /* declarations for DLL import */
393388
#define DL_IMPORT(RTYPE) RTYPE
394389
#endif
395390

396-
#ifdef MALLOC_ZERO_RETURNS_NULL
397-
/* Allocate an extra byte if the platform malloc(0) returns NULL.
398-
Caution: this bears no relation to whether realloc(p, 0) returns NULL
399-
when p != NULL. Even on platforms where malloc(0) does not return NULL,
400-
realloc(p, 0) may act like free(p) and return NULL. Examples include
401-
Windows, and Python's own obmalloc.c (as of 2-Mar-2002). For whatever
402-
reason, our docs promise that PyMem_Realloc(p, 0) won't act like
403-
free(p) or return NULL, so realloc() calls may have to be hacked
404-
too, but MALLOC_ZERO_RETURNS_NULL's state is irrelevant to realloc (it
405-
needs a different hack).
406-
*/
407-
#define _PyMem_EXTRA 1
408-
#else
409-
#define _PyMem_EXTRA 0
410-
#endif
411-
412-
413391
/* If the fd manipulation macros aren't defined,
414392
here is a set that should do the job */
415393

Modules/pypcre.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3078,8 +3078,11 @@ static int grow_stack(match_data *md)
30783078
else {md->length = 80;}
30793079
}
30803080
PyMem_RESIZE(md->offset_top, int, md->length);
3081-
PyMem_RESIZE(md->eptr, const uschar *, md->length);
3082-
PyMem_RESIZE(md->ecode, const uschar *, md->length);
3081+
/* Can't realloc a pointer-to-const; cast const away. */
3082+
md->eptr = (const uschar **)PyMem_Realloc((void *)md->eptr,
3083+
sizeof(uschar *) * md->length);
3084+
md->ecode = (const uschar **)PyMem_Realloc((void *)md->ecode,
3085+
sizeof(uschar *) * md->length);
30833086
PyMem_RESIZE(md->off_num, int, md->length);
30843087
PyMem_RESIZE(md->r1, int, md->length);
30853088
PyMem_RESIZE(md->r2, int, md->length);

Objects/object.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,18 +1897,13 @@ int (*_Py_abstract_hack)(PyObject *) = &PyObject_Size;
18971897
void *
18981898
PyMem_Malloc(size_t nbytes)
18991899
{
1900-
#if _PyMem_EXTRA > 0
1901-
if (nbytes == 0)
1902-
nbytes = _PyMem_EXTRA;
1903-
#endif
19041900
return PyMem_MALLOC(nbytes);
19051901
}
19061902

19071903
void *
19081904
PyMem_Realloc(void *p, size_t nbytes)
19091905
{
1910-
/* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */
1911-
return PyMem_REALLOC(p, nbytes ? nbytes : 1);
1906+
return PyMem_REALLOC(p, nbytes);
19121907
}
19131908

19141909
void

0 commit comments

Comments
 (0)