Skip to content

Commit 9820c07

Browse files
authored
bpo-35134: Add Include/cpython/pymem.h (GH-12840)
Move unstable CPython API from Include/pymem.h into a new Include/cpython/pymem.h header file.
1 parent a3283ef commit 9820c07

File tree

2 files changed

+106
-95
lines changed

2 files changed

+106
-95
lines changed

Include/cpython/pymem.h

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#ifndef Py_CPYTHON_PYMEM_H
2+
# error "this header file must not be included directly"
3+
#endif
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size);
10+
PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize);
11+
PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size);
12+
PyAPI_FUNC(void) PyMem_RawFree(void *ptr);
13+
14+
/* Configure the Python memory allocators. Pass NULL to use default
15+
allocators. */
16+
PyAPI_FUNC(int) _PyMem_SetupAllocators(const char *opt);
17+
18+
/* Try to get the allocators name set by _PyMem_SetupAllocators(). */
19+
PyAPI_FUNC(const char*) _PyMem_GetAllocatorsName(void);
20+
21+
PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize);
22+
23+
/* strdup() using PyMem_RawMalloc() */
24+
PyAPI_FUNC(char *) _PyMem_RawStrdup(const char *str);
25+
26+
/* strdup() using PyMem_Malloc() */
27+
PyAPI_FUNC(char *) _PyMem_Strdup(const char *str);
28+
29+
/* wcsdup() using PyMem_RawMalloc() */
30+
PyAPI_FUNC(wchar_t*) _PyMem_RawWcsdup(const wchar_t *str);
31+
32+
33+
typedef enum {
34+
/* PyMem_RawMalloc(), PyMem_RawRealloc() and PyMem_RawFree() */
35+
PYMEM_DOMAIN_RAW,
36+
37+
/* PyMem_Malloc(), PyMem_Realloc() and PyMem_Free() */
38+
PYMEM_DOMAIN_MEM,
39+
40+
/* PyObject_Malloc(), PyObject_Realloc() and PyObject_Free() */
41+
PYMEM_DOMAIN_OBJ
42+
} PyMemAllocatorDomain;
43+
44+
typedef struct {
45+
/* user context passed as the first argument to the 4 functions */
46+
void *ctx;
47+
48+
/* allocate a memory block */
49+
void* (*malloc) (void *ctx, size_t size);
50+
51+
/* allocate a memory block initialized by zeros */
52+
void* (*calloc) (void *ctx, size_t nelem, size_t elsize);
53+
54+
/* allocate or resize a memory block */
55+
void* (*realloc) (void *ctx, void *ptr, size_t new_size);
56+
57+
/* release a memory block */
58+
void (*free) (void *ctx, void *ptr);
59+
} PyMemAllocatorEx;
60+
61+
/* Get the memory block allocator of the specified domain. */
62+
PyAPI_FUNC(void) PyMem_GetAllocator(PyMemAllocatorDomain domain,
63+
PyMemAllocatorEx *allocator);
64+
65+
/* Set the memory block allocator of the specified domain.
66+
67+
The new allocator must return a distinct non-NULL pointer when requesting
68+
zero bytes.
69+
70+
For the PYMEM_DOMAIN_RAW domain, the allocator must be thread-safe: the GIL
71+
is not held when the allocator is called.
72+
73+
If the new allocator is not a hook (don't call the previous allocator), the
74+
PyMem_SetupDebugHooks() function must be called to reinstall the debug hooks
75+
on top on the new allocator. */
76+
PyAPI_FUNC(void) PyMem_SetAllocator(PyMemAllocatorDomain domain,
77+
PyMemAllocatorEx *allocator);
78+
79+
/* Setup hooks to detect bugs in the following Python memory allocator
80+
functions:
81+
82+
- PyMem_RawMalloc(), PyMem_RawRealloc(), PyMem_RawFree()
83+
- PyMem_Malloc(), PyMem_Realloc(), PyMem_Free()
84+
- PyObject_Malloc(), PyObject_Realloc() and PyObject_Free()
85+
86+
Newly allocated memory is filled with the byte 0xCB, freed memory is filled
87+
with the byte 0xDB. Additional checks:
88+
89+
- detect API violations, ex: PyObject_Free() called on a buffer allocated
90+
by PyMem_Malloc()
91+
- detect write before the start of the buffer (buffer underflow)
92+
- detect write after the end of the buffer (buffer overflow)
93+
94+
The function does nothing if Python is not compiled is debug mode. */
95+
PyAPI_FUNC(void) PyMem_SetupDebugHooks(void);
96+
97+
#ifdef __cplusplus
98+
}
99+
#endif

Include/pymem.h

Lines changed: 7 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,6 @@
1111
extern "C" {
1212
#endif
1313

14-
#ifndef Py_LIMITED_API
15-
PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size);
16-
PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize);
17-
PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size);
18-
PyAPI_FUNC(void) PyMem_RawFree(void *ptr);
19-
20-
/* Configure the Python memory allocators. Pass NULL to use default
21-
allocators. */
22-
PyAPI_FUNC(int) _PyMem_SetupAllocators(const char *opt);
23-
24-
/* Try to get the allocators name set by _PyMem_SetupAllocators(). */
25-
PyAPI_FUNC(const char*) _PyMem_GetAllocatorsName(void);
26-
#endif /* !defined(Py_LIMITED_API) */
27-
28-
2914
/* BEWARE:
3015
3116
Each interface exports both functions and macros. Extension modules should
@@ -65,23 +50,9 @@ PyAPI_FUNC(const char*) _PyMem_GetAllocatorsName(void);
6550
*/
6651

6752
PyAPI_FUNC(void *) PyMem_Malloc(size_t size);
68-
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03050000
69-
PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize);
70-
#endif
7153
PyAPI_FUNC(void *) PyMem_Realloc(void *ptr, size_t new_size);
7254
PyAPI_FUNC(void) PyMem_Free(void *ptr);
7355

74-
#ifndef Py_LIMITED_API
75-
/* strdup() using PyMem_RawMalloc() */
76-
PyAPI_FUNC(char *) _PyMem_RawStrdup(const char *str);
77-
78-
/* strdup() using PyMem_Malloc() */
79-
PyAPI_FUNC(char *) _PyMem_Strdup(const char *str);
80-
81-
/* wcsdup() using PyMem_RawMalloc() */
82-
PyAPI_FUNC(wchar_t*) _PyMem_RawWcsdup(const wchar_t *str);
83-
#endif
84-
8556
/* Macros. */
8657

8758
/* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL
@@ -130,72 +101,6 @@ PyAPI_FUNC(wchar_t*) _PyMem_RawWcsdup(const wchar_t *str);
130101
#define PyMem_Del PyMem_Free
131102
#define PyMem_DEL PyMem_FREE
132103

133-
#ifndef Py_LIMITED_API
134-
typedef enum {
135-
/* PyMem_RawMalloc(), PyMem_RawRealloc() and PyMem_RawFree() */
136-
PYMEM_DOMAIN_RAW,
137-
138-
/* PyMem_Malloc(), PyMem_Realloc() and PyMem_Free() */
139-
PYMEM_DOMAIN_MEM,
140-
141-
/* PyObject_Malloc(), PyObject_Realloc() and PyObject_Free() */
142-
PYMEM_DOMAIN_OBJ
143-
} PyMemAllocatorDomain;
144-
145-
typedef struct {
146-
/* user context passed as the first argument to the 4 functions */
147-
void *ctx;
148-
149-
/* allocate a memory block */
150-
void* (*malloc) (void *ctx, size_t size);
151-
152-
/* allocate a memory block initialized by zeros */
153-
void* (*calloc) (void *ctx, size_t nelem, size_t elsize);
154-
155-
/* allocate or resize a memory block */
156-
void* (*realloc) (void *ctx, void *ptr, size_t new_size);
157-
158-
/* release a memory block */
159-
void (*free) (void *ctx, void *ptr);
160-
} PyMemAllocatorEx;
161-
162-
/* Get the memory block allocator of the specified domain. */
163-
PyAPI_FUNC(void) PyMem_GetAllocator(PyMemAllocatorDomain domain,
164-
PyMemAllocatorEx *allocator);
165-
166-
/* Set the memory block allocator of the specified domain.
167-
168-
The new allocator must return a distinct non-NULL pointer when requesting
169-
zero bytes.
170-
171-
For the PYMEM_DOMAIN_RAW domain, the allocator must be thread-safe: the GIL
172-
is not held when the allocator is called.
173-
174-
If the new allocator is not a hook (don't call the previous allocator), the
175-
PyMem_SetupDebugHooks() function must be called to reinstall the debug hooks
176-
on top on the new allocator. */
177-
PyAPI_FUNC(void) PyMem_SetAllocator(PyMemAllocatorDomain domain,
178-
PyMemAllocatorEx *allocator);
179-
180-
/* Setup hooks to detect bugs in the following Python memory allocator
181-
functions:
182-
183-
- PyMem_RawMalloc(), PyMem_RawRealloc(), PyMem_RawFree()
184-
- PyMem_Malloc(), PyMem_Realloc(), PyMem_Free()
185-
- PyObject_Malloc(), PyObject_Realloc() and PyObject_Free()
186-
187-
Newly allocated memory is filled with the byte 0xCB, freed memory is filled
188-
with the byte 0xDB. Additional checks:
189-
190-
- detect API violations, ex: PyObject_Free() called on a buffer allocated
191-
by PyMem_Malloc()
192-
- detect write before the start of the buffer (buffer underflow)
193-
- detect write after the end of the buffer (buffer overflow)
194-
195-
The function does nothing if Python is not compiled is debug mode. */
196-
PyAPI_FUNC(void) PyMem_SetupDebugHooks(void);
197-
#endif /* Py_LIMITED_API */
198-
199104
/* bpo-35053: expose _Py_tracemalloc_config for performance:
200105
_Py_NewReference() needs an efficient check to test if tracemalloc is
201106
tracing.
@@ -231,6 +136,13 @@ PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config;
231136
.max_nframe = 1, \
232137
.use_domain = 0}
233138

139+
140+
#ifndef Py_LIMITED_API
141+
# define Py_CPYTHON_PYMEM_H
142+
# include "cpython/pymem.h"
143+
# undef Py_CPYTHON_PYMEM_H
144+
#endif
145+
234146
#ifdef __cplusplus
235147
}
236148
#endif

0 commit comments

Comments
 (0)