jpayne@69: /* The PyMem_ family: low-level memory allocation interfaces. jpayne@69: See objimpl.h for the PyObject_ memory family. jpayne@69: */ jpayne@69: jpayne@69: #ifndef Py_PYMEM_H jpayne@69: #define Py_PYMEM_H jpayne@69: jpayne@69: #include "pyport.h" jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: extern "C" { jpayne@69: #endif jpayne@69: jpayne@69: /* BEWARE: jpayne@69: jpayne@69: Each interface exports both functions and macros. Extension modules should jpayne@69: use the functions, to ensure binary compatibility across Python versions. jpayne@69: Because the Python implementation is free to change internal details, and jpayne@69: the macros may (or may not) expose details for speed, if you do use the jpayne@69: macros you must recompile your extensions with each Python release. jpayne@69: jpayne@69: Never mix calls to PyMem_ with calls to the platform malloc/realloc/ jpayne@69: calloc/free. For example, on Windows different DLLs may end up using jpayne@69: different heaps, and if you use PyMem_Malloc you'll get the memory from the jpayne@69: heap used by the Python DLL; it could be a disaster if you free()'ed that jpayne@69: directly in your own extension. Using PyMem_Free instead ensures Python jpayne@69: can return the memory to the proper heap. As another example, in jpayne@69: PYMALLOC_DEBUG mode, Python wraps all calls to all PyMem_ and PyObject_ jpayne@69: memory functions in special debugging wrappers that add additional jpayne@69: debugging info to dynamic memory blocks. The system routines have no idea jpayne@69: what to do with that stuff, and the Python wrappers have no idea what to do jpayne@69: with raw blocks obtained directly by the system routines then. jpayne@69: jpayne@69: The GIL must be held when using these APIs. jpayne@69: */ jpayne@69: jpayne@69: /* jpayne@69: * Raw memory interface jpayne@69: * ==================== jpayne@69: */ jpayne@69: jpayne@69: /* Functions jpayne@69: jpayne@69: Functions supplying platform-independent semantics for malloc/realloc/ jpayne@69: free. These functions make sure that allocating 0 bytes returns a distinct jpayne@69: non-NULL pointer (whenever possible -- if we're flat out of memory, NULL jpayne@69: may be returned), even if the platform malloc and realloc don't. jpayne@69: Returned pointers must be checked for NULL explicitly. No action is jpayne@69: performed on failure (no exception is set, no warning is printed, etc). jpayne@69: */ jpayne@69: jpayne@69: PyAPI_FUNC(void *) PyMem_Malloc(size_t size); jpayne@69: PyAPI_FUNC(void *) PyMem_Realloc(void *ptr, size_t new_size); jpayne@69: PyAPI_FUNC(void) PyMem_Free(void *ptr); jpayne@69: jpayne@69: /* Macros. */ jpayne@69: jpayne@69: /* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL jpayne@69: for malloc(0), which would be treated as an error. Some platforms jpayne@69: would return a pointer with no memory behind it, which would break jpayne@69: pymalloc. To solve these problems, allocate an extra byte. */ jpayne@69: /* Returns NULL to indicate error if a negative size or size larger than jpayne@69: Py_ssize_t can represent is supplied. Helps prevents security holes. */ jpayne@69: #define PyMem_MALLOC(n) PyMem_Malloc(n) jpayne@69: #define PyMem_REALLOC(p, n) PyMem_Realloc(p, n) jpayne@69: #define PyMem_FREE(p) PyMem_Free(p) jpayne@69: jpayne@69: /* jpayne@69: * Type-oriented memory interface jpayne@69: * ============================== jpayne@69: * jpayne@69: * Allocate memory for n objects of the given type. Returns a new pointer jpayne@69: * or NULL if the request was too large or memory allocation failed. Use jpayne@69: * these macros rather than doing the multiplication yourself so that proper jpayne@69: * overflow checking is always done. jpayne@69: */ jpayne@69: jpayne@69: #define PyMem_New(type, n) \ jpayne@69: ( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ jpayne@69: ( (type *) PyMem_Malloc((n) * sizeof(type)) ) ) jpayne@69: #define PyMem_NEW(type, n) \ jpayne@69: ( ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ jpayne@69: ( (type *) PyMem_MALLOC((n) * sizeof(type)) ) ) jpayne@69: jpayne@69: /* jpayne@69: * The value of (p) is always clobbered by this macro regardless of success. jpayne@69: * The caller MUST check if (p) is NULL afterwards and deal with the memory jpayne@69: * error if so. This means the original value of (p) MUST be saved for the jpayne@69: * caller's memory error handler to not lose track of it. jpayne@69: */ jpayne@69: #define PyMem_Resize(p, type, n) \ jpayne@69: ( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ jpayne@69: (type *) PyMem_Realloc((p), (n) * sizeof(type)) ) jpayne@69: #define PyMem_RESIZE(p, type, n) \ jpayne@69: ( (p) = ((size_t)(n) > PY_SSIZE_T_MAX / sizeof(type)) ? NULL : \ jpayne@69: (type *) PyMem_REALLOC((p), (n) * sizeof(type)) ) jpayne@69: jpayne@69: /* PyMem{Del,DEL} are left over from ancient days, and shouldn't be used jpayne@69: * anymore. They're just confusing aliases for PyMem_{Free,FREE} now. jpayne@69: */ jpayne@69: #define PyMem_Del PyMem_Free jpayne@69: #define PyMem_DEL PyMem_FREE jpayne@69: jpayne@69: /* bpo-35053: expose _Py_tracemalloc_config for performance: jpayne@69: _Py_NewReference() needs an efficient check to test if tracemalloc is jpayne@69: tracing. jpayne@69: jpayne@69: It has to be defined in pymem.h, before object.h is included. */ jpayne@69: struct _PyTraceMalloc_Config { jpayne@69: /* Module initialized? jpayne@69: Variable protected by the GIL */ jpayne@69: enum { jpayne@69: TRACEMALLOC_NOT_INITIALIZED, jpayne@69: TRACEMALLOC_INITIALIZED, jpayne@69: TRACEMALLOC_FINALIZED jpayne@69: } initialized; jpayne@69: jpayne@69: /* Is tracemalloc tracing memory allocations? jpayne@69: Variable protected by the GIL */ jpayne@69: int tracing; jpayne@69: jpayne@69: /* limit of the number of frames in a traceback, 1 by default. jpayne@69: Variable protected by the GIL. */ jpayne@69: int max_nframe; jpayne@69: jpayne@69: /* use domain in trace key? jpayne@69: Variable protected by the GIL. */ jpayne@69: int use_domain; jpayne@69: }; jpayne@69: jpayne@69: PyAPI_DATA(struct _PyTraceMalloc_Config) _Py_tracemalloc_config; jpayne@69: jpayne@69: #define _PyTraceMalloc_Config_INIT \ jpayne@69: {.initialized = TRACEMALLOC_NOT_INITIALIZED, \ jpayne@69: .tracing = 0, \ jpayne@69: .max_nframe = 1, \ jpayne@69: .use_domain = 0} jpayne@69: jpayne@69: jpayne@69: #ifndef Py_LIMITED_API jpayne@69: # define Py_CPYTHON_PYMEM_H jpayne@69: # include "cpython/pymem.h" jpayne@69: # undef Py_CPYTHON_PYMEM_H jpayne@69: #endif jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: } jpayne@69: #endif jpayne@69: jpayne@69: #endif /* !Py_PYMEM_H */