Minneshantering¶
Översikt¶
Minneshantering i Python innebär en privat hög som innehåller alla Python-objekt och datastrukturer. Hanteringen av denna privata hög sköts internt av Pythons minneshanterare. Pythons minneshanterare har olika komponenter som hanterar olika aspekter av dynamisk lagringshantering, t.ex. delning, segmentering, förallokering eller cachning.
På den lägsta nivån ser en råminnesallokerare till att det finns tillräckligt med utrymme i den privata heapen för att lagra alla Python-relaterade data genom att interagera med operativsystemets minneshanterare. Utöver råminnesallokeringen arbetar flera objektspecifika allokeringar på samma hög och implementerar olika minneshanteringspolicyer som är anpassade till varje objekttyps särdrag. Exempelvis hanteras heltalsobjekt annorlunda i heapen än strängar, tupler eller dictionaries eftersom heltal innebär olika lagringskrav och avvägningar mellan hastighet och utrymme. Pythons minneshanterare delegerar således en del av arbetet till de objektspecifika allokeringarna, men ser till att de senare arbetar inom gränserna för den privata heapen.
Det är viktigt att förstå att hanteringen av Pythons heap utförs av tolken själv och att användaren inte har någon kontroll över den, även om de regelbundet manipulerar objektpekare till minnesblock inuti heapen. Allokeringen av heaputrymme för Python-objekt och andra interna buffertar utförs på begäran av Pythons minneshanterare genom de Python/C API-funktioner som listas i detta dokument.
För att undvika minneskorruption bör författare av tillägg aldrig försöka använda Python-objekt med de funktioner som exporteras av C-biblioteket: malloc()
, calloc()
, realloc()
och free()
. Detta kommer att resultera i blandade anrop mellan C-allokatorn och Pythons minneshanterare med fatala konsekvenser, eftersom de implementerar olika algoritmer och arbetar på olika heaps. Man kan dock på ett säkert sätt allokera och frigöra minnesblock med C-bibliotekets allokator för individuella ändamål, som visas i följande exempel:
PyObject *res;
char *buf = (char *) malloc(BUFSIZ); /* för I/O */
om (buf == NULL)
return PyErr_NoMemory();
...Gör någon I/O-operation som involverar buf...
res = PyBytes_FromString(buf);
free(buf); /* malloc'ed */
returnera res;
I det här exemplet hanteras minnesbegäran för I/O-bufferten av C-bibliotekets allokator. Pythons minneshanterare är endast involverad i allokeringen av bytesobjektet som returneras som ett resultat.
I de flesta situationer är det dock rekommenderat att allokera minne från Pythons heap, just för att den senare står under kontroll av Pythons minneshanterare. Detta krävs till exempel när tolken utökas med nya objekttyper skrivna i C. En annan anledning till att använda Python-heapen är önskan att informera Pythons minneshanterare om minnesbehoven i tilläggsmodulen. Även när det begärda minnet uteslutande används för interna, mycket specifika ändamål, leder delegeringen av alla minnesförfrågningar till Pythons minneshanterare till att tolken får en mer exakt bild av sitt minnesavtryck som helhet. Följaktligen kan Pythons minneshanterare under vissa omständigheter utlösa lämpliga åtgärder, t.ex. sopsortering, minneskomprimering eller andra förebyggande åtgärder. Observera att genom att använda C-bibliotekets allokator som visas i föregående exempel, undgår det allokerade minnet för I/O-bufferten helt Pythons minneshanterare.
Se även
Miljövariabeln PYTHONMALLOC
kan användas för att konfigurera de minnesallokatorer som används av Python.
Miljövariabeln PYTHONMALLOCSTATS
kan användas för att skriva ut statistik för pymalloc memory allocator varje gång en ny pymalloc-objektarena skapas och vid avstängning.
Domäner för allokering¶
Alla allokeringsfunktioner tillhör en av tre olika ”domäner” (se även PyMemAllocatorDomain
). Dessa domäner representerar olika allokeringsstrategier och är optimerade för olika ändamål. De specifika detaljerna om hur varje domän allokerar minne eller vilka interna funktioner som varje domän anropar anses vara en implementationsdetalj, men för felsökningsändamål finns en förenklad tabell på here. De API:er som används för att allokera och frigöra ett minnesblock måste vara från samma domän. Till exempel måste PyMem_Free()
användas för att frigöra minne som allokerats med PyMem_Malloc()
.
De tre tilldelningsdomänerna är:
Rå domän: avsedd för allokering av minne för allmänna minnesbuffertar där allokeringen måste gå till systemets allokator eller där allokatorn kan fungera utan ett attached thread state. Minnet begärs direkt från systemet. Se Raw Memory Interface.
”Mem”-domän: avsedd för allokering av minne för Python-buffertar och allmänna minnesbuffertar där allokeringen måste utföras med en attached thread state. Minnet tas från Pythons privata heap. Se Memory Interface.
Objektdomän: avsedd för att allokera minne för Python-objekt. Minnet tas från Pythons privata heap. Se Objektallokatorer.
Anteckning
Byggning med free-threaded kräver att endast Python-objekt allokeras med hjälp av domänen ”object” och att alla Python-objekt allokeras med hjälp av den domänen. Detta skiljer sig från de tidigare Python-versionerna, där detta endast var en bästa praxis och inte ett hårt krav.
Till exempel bör buffertar (icke-Python-objekt) allokeras med PyMem_Malloc()
, PyMem_RawMalloc()
eller malloc()
, men inte med PyObject_Malloc()
.
Gränssnitt för råminne¶
Följande funktionsuppsättningar är omslag till systemallokatorn. Dessa funktioner är tråd-säkra, så en thread state behöver inte vara attached.
standardminnesallokatorn använder följande funktioner: malloc()
, calloc()
, realloc()
och free()
; anropa malloc(1)
(eller calloc(1, 1)
) när du begär noll byte.
Tillagd i version 3.4.
-
void *PyMem_RawMalloc(size_t n)¶
- En del av Stabil ABI sedan version 3.13.
Allokerar n byte och returnerar en pekare av typen void* till det allokerade minnet, eller
NULL
om begäran misslyckas.En begäran om noll bytes returnerar en distinkt pekare som inte är
NULL
om möjligt, som omPyMem_RawMalloc(1)
hade anropats istället. Minnet kommer inte att ha initialiserats på något sätt.
-
void *PyMem_RawCalloc(size_t nelem, size_t elsize)¶
- En del av Stabil ABI sedan version 3.13.
Allokerar nelem element vars storlek i byte är elsize och returnerar en pekare av typen void* till det allokerade minnet, eller
NULL
om begäran misslyckas. Minnet initialiseras till nollor.Om man begär noll element eller element med storleken noll bytes returneras en distinkt icke-
NULL
pekare om möjligt, som omPyMem_RawCalloc(1, 1)
hade anropats istället.Tillagd i version 3.5.
-
void *PyMem_RawRealloc(void *p, size_t n)¶
- En del av Stabil ABI sedan version 3.13.
Ändrar storlek på minnesblocket som pekas ut av p till n byte. Innehållet kommer att vara oförändrat till det minsta av den gamla och den nya storleken.
Om p är
NULL
motsvarar anropetPyMem_RawMalloc(n)
; om n är lika med noll ändras minnesblockets storlek men det frigörs inte och den returnerade pekaren är inteNULL
.Om inte p är
NULL
måste den ha returnerats av ett tidigare anrop tillPyMem_RawMalloc()
,PyMem_RawRealloc()
ellerPyMem_RawCalloc()
.Om begäran misslyckas returnerar
PyMem_RawRealloc()
NULL
och p förblir en giltig pekare till det föregående minnesområdet.
-
void PyMem_RawFree(void *p)¶
- En del av Stabil ABI sedan version 3.13.
Frigör minnesblocket som pekas ut av p, vilket måste ha returnerats av ett tidigare anrop till
PyMem_RawMalloc()
,PyMem_RawRealloc()
ellerPyMem_RawCalloc()
. Annars, eller omPyMem_RawFree(p)
har anropats tidigare, uppstår ett odefinierat beteende.Om p är
NULL
utförs ingen åtgärd.
Minnesgränssnitt¶
Följande funktionsuppsättningar, som är modellerade efter ANSI C-standarden, men som specificerar beteendet när noll byte begärs, är tillgängliga för att allokera och frigöra minne från Pythons heap.
I default memory allocator används pymalloc memory allocator.
Varning
Det måste finnas en attached thread state när dessa funktioner används.
Ändrad i version 3.6: Standardallokeraren är nu pymalloc istället för system malloc()
.
-
void *PyMem_Malloc(size_t n)¶
- En del av Stabil ABI.
Allokerar n byte och returnerar en pekare av typen void* till det allokerade minnet, eller
NULL
om begäran misslyckas.En begäran om noll bytes returnerar en distinkt pekare som inte är
NULL
om möjligt, som omPyMem_Malloc(1)
hade anropats istället. Minnet kommer inte att ha initialiserats på något sätt.
-
void *PyMem_Calloc(size_t nelem, size_t elsize)¶
- En del av Stabil ABI sedan version 3.7.
Allokerar nelem element vars storlek i byte är elsize och returnerar en pekare av typen void* till det allokerade minnet, eller
NULL
om begäran misslyckas. Minnet initialiseras till nollor.Om man begär noll element eller element med storleken noll bytes returneras en distinkt icke-
NULL
pekare om möjligt, som omPyMem_Calloc(1, 1)
hade anropats istället.Tillagd i version 3.5.
-
void *PyMem_Realloc(void *p, size_t n)¶
- En del av Stabil ABI.
Ändrar storlek på minnesblocket som pekas ut av p till n byte. Innehållet kommer att vara oförändrat till det minsta av den gamla och den nya storleken.
Om p är
NULL
motsvarar anropetPyMem_Malloc(n)
; om n är lika med noll ändras minnesblockets storlek men det frigörs inte och den returnerade pekaren är inteNULL
.Om inte p är
NULL
måste den ha returnerats av ett tidigare anrop tillPyMem_Malloc()
,PyMem_Realloc()
ellerPyMem_Calloc()
.Om begäran misslyckas returnerar
PyMem_Realloc()
NULL
och p förblir en giltig pekare till det föregående minnesområdet.
-
void PyMem_Free(void *p)¶
- En del av Stabil ABI.
Frigör minnesblocket som pekas ut av p, vilket måste ha returnerats av ett tidigare anrop till
PyMem_Malloc()
,PyMem_Realloc()
ellerPyMem_Calloc()
. Annars, eller omPyMem_Free(p)
har anropats tidigare, uppstår ett odefinierat beteende.Om p är
NULL
utförs ingen åtgärd.
Följande typorienterade makron tillhandahålls för enkelhetens skull. Observera att TYPE hänvisar till vilken C-typ som helst.
-
PyMem_New(TYPE, n)¶
Samma som
PyMem_Malloc()
, men allokerar(n * sizeof(TYPE))
bytes minne. Returnerar en pekare som kastas tillTYPE*
. Minnet kommer inte att ha initialiserats på något sätt.
-
PyMem_Resize(p, TYPE, n)¶
Samma som
PyMem_Realloc()
, men minnesblocket ändras till(n * sizeof(TYPE))
bytes. Returnerar en pekare som kastats tillTYPE*
. Vid retur kommer p att vara en pekare till det nya minnesområdet, ellerNULL
i händelse av fel.Detta är ett C preprocessormakro; p är alltid återtilldelad. Spara originalvärdet för p för att undvika minnesförlust vid felhantering.
-
void PyMem_Del(void *p)¶
Samma som
PyMem_Free()
.
Dessutom finns följande makrouppsättningar för att anropa Pythons minnesallokator direkt, utan att involvera C API-funktionerna som listas ovan. Observera dock att användningen av dessa inte bevarar binär kompatibilitet mellan olika Python-versioner och därför inte rekommenderas i tilläggsmoduler.
PyMem_MALLOC(size)
PyMem_NEW(type, size)
PyMem_REALLOC(ptr, size)
PyMem_RESIZE(ptr, type, size)
PyMem_FREE(ptr)
PyMem_DEL(ptr)
Objektallokatorer¶
Följande funktionsuppsättningar, som är modellerade efter ANSI C-standarden, men som specificerar beteendet när noll byte begärs, är tillgängliga för att allokera och frigöra minne från Pythons heap.
Anteckning
Det finns ingen garanti för att det minne som returneras av dessa allokeringsfunktioner framgångsrikt kan kastas till ett Python-objekt när man avlyssnar allokeringsfunktionerna i den här domänen med de metoder som beskrivs i avsnittet Customize Memory Allocators.
I default object allocator används pymalloc memory allocator.
Varning
Det måste finnas en attached thread state när dessa funktioner används.
-
void *PyObject_Malloc(size_t n)¶
- En del av Stabil ABI.
Allokerar n byte och returnerar en pekare av typen void* till det allokerade minnet, eller
NULL
om begäran misslyckas.Om noll bytes begärs returneras en distinkt icke-
NULL
pekare om möjligt, som omPyObject_Malloc(1)
hade anropats istället. Minnet kommer inte att ha initialiserats på något sätt.
-
void *PyObject_Calloc(size_t nelem, size_t elsize)¶
- En del av Stabil ABI sedan version 3.7.
Allokerar nelem element vars storlek i byte är elsize och returnerar en pekare av typen void* till det allokerade minnet, eller
NULL
om begäran misslyckas. Minnet initialiseras till nollor.Om man begär noll element eller element med storleken noll bytes returneras en distinkt icke-
NULL
pekare om möjligt, som omPyObject_Calloc(1, 1)
hade anropats istället.Tillagd i version 3.5.
-
void *PyObject_Realloc(void *p, size_t n)¶
- En del av Stabil ABI.
Ändrar storlek på minnesblocket som pekas ut av p till n byte. Innehållet kommer att vara oförändrat till det minsta av den gamla och den nya storleken.
Om p är
NULL
motsvarar anropetPyObject_Malloc(n)
; om n är lika med noll ändras minnesblockets storlek men det frigörs inte och den returnerade pekaren är inteNULL
.Om inte p är
NULL
måste den ha returnerats av ett tidigare anrop tillPyObject_Malloc()
,PyObject_Realloc()
ellerPyObject_Calloc()
.Om begäran misslyckas returnerar
PyObject_Realloc()
NULL
och p förblir en giltig pekare till det tidigare minnesområdet.
-
void PyObject_Free(void *p)¶
- En del av Stabil ABI.
Frigör minnesblocket som pekas ut av p, vilket måste ha returnerats av ett tidigare anrop till
PyObject_Malloc()
,PyObject_Realloc()
ellerPyObject_Calloc()
. Annars, eller omPyObject_Free(p)
har anropats tidigare, uppstår ett odefinierat beteende.Om p är
NULL
utförs ingen åtgärd.Anropa inte detta direkt för att frigöra ett objekts minne; anropa istället typens
tp_free
slot.Använd inte detta för minne som allokerats av
PyObject_GC_New
ellerPyObject_GC_NewVar
; använd iställetPyObject_GC_Del()
.Se även
PyObject_GC_Del()
är motsvarigheten till denna funktion för minne som allokerats av typer som stöder garbage collection.
Standard minnesallokatorer¶
Standardminnesallokatorer:
Konfiguration |
Namn |
PyMem_RawMalloc |
PyMem_Malloc |
PyObject_Malloc |
---|---|---|---|---|
Release-version |
|
|
|
|
Felsök byggnaden |
|
|
|
|
Release-version, utan pymalloc |
|
|
|
|
Felsökning, utan pymalloc |
|
|
|
|
Legend:
Namn: värde för miljövariabeln
PYTHONMALLOC
.malloc
: systemallokatorer från standard C-biblioteket, C-funktioner:malloc()
,calloc()
,realloc()
ochfree()
.pymalloc
: pymalloc minnesallokering.mimalloc
: mimalloc minnesallokator. Allokeraren pymalloc kommer att användas om stöd för mimalloc inte finns tillgängligt.”+ debug”: med felsöknings-hooks på Pythons minnesallokatorer.
”Debug build”: Python byggs i felsökningsläge.
Anpassa minnesfördelare¶
Tillagd i version 3.4.
-
type PyMemAllocatorEx¶
Struktur som används för att beskriva en minnesblocksallokering. Strukturen har följande fält:
Fält
Betydelse
void *ctx
användarkontext som skickas som första argument
void* malloc(void *ctx, size_t size)
allokera ett minnesblock
void* calloc(void *ctx, size_t nelem, size_t elsize)
allokera ett minnesblock som initieras med nollor
void* realloc(void *ctx, void *ptr, size_t new_size)
allokera eller ändra storlek på ett minnesblock
void free(void *ctx, void *ptr)
frigöra ett minnesblock
Ändrad i version 3.5: Strukturen
PyMemAllocator
döptes om tillPyMemAllocatorEx
och ett nytt fältcalloc
lades till.
-
type PyMemAllocatorDomain¶
Enum som används för att identifiera en allokeringsdomän. Domäner:
-
PYMEM_DOMAIN_RAW¶
Funktioner:
-
PYMEM_DOMAIN_MEM¶
Funktioner:
-
PYMEM_DOMAIN_OBJ¶
Funktioner:
-
PYMEM_DOMAIN_RAW¶
-
void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)¶
Hämta minnesblockstilldelaren för den angivna domänen.
-
void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocatorEx *allocator)¶
Ställ in minnesblocksallokeringen för den angivna domänen.
Den nya allokeraren måste returnera en distinkt pekare som inte är
NULL
när den begär noll bytes.För domänen
PYMEM_DOMAIN_RAW
måste allokeraren vara tråd-säker: ett thread state är inte attached när allokeraren anropas.För de återstående domänerna måste allokeraren också vara tråd-säker: allokeraren kan anropas i olika tolkare som inte delar en GIL.
Om den nya allokeringsenheten inte är en hook (anropar inte den föregående allokeringsenheten) måste funktionen
PyMem_SetupDebugHooks()
anropas för att installera om debughooks ovanpå den nya allokeringsenheten.Se även
PyPreConfig.allocator
och Preinitialisera Python med PyPreConfig.Varning
PyMem_SetAllocator()
har följande kontrakt:Den kan anropas efter
Py_PreInitialize()
och förePy_InitializeFromConfig()
för att installera en anpassad minnesallokering. Det finns inga andra begränsningar för den installerade allokatorn än de som domänen inför (till exempel tillåter Raw Domain att allokatorn anropas utan en attached thread state). Se avsnittet om allokeringsdomäner för mer information.Om den anropas efter att Python har slutfört initialiseringen (efter att
Py_InitializeFromConfig()
har anropats) måste allokatorn omhölja den befintliga allokatorn. Att ersätta den aktuella allokatorn med någon annan godtycklig allokator stöds inte.
Ändrad i version 3.12: Alla allokatorer måste vara trådsäkra.
-
void PyMem_SetupDebugHooks(void)¶
Installera debug-hooks i Pythons minnesallokatorer för att upptäcka minnesfel.
Felsöknings-hooks på Pythons minnesallokatorer¶
När Python byggs i felsökningsläge, anropas funktionen PyMem_SetupDebugHooks()
vid Pythons förinitialisering för att ställa in felsöknings-hooks på Pythons minnesallokatorer för att upptäcka minnesfel.
Miljövariabeln PYTHONMALLOC
kan användas för att installera debug-hooks på ett Python som kompilerats i release-läge (ex: PYTHONMALLOC=debug
).
Funktionen PyMem_SetupDebugHooks()
kan användas för att ställa in debug-hooks efter anrop av PyMem_SetAllocator()
.
Dessa debughooks fyller dynamiskt allokerade minnesblock med speciella, igenkännbara bitmönster. Nytilldelat minne fylls med bytena 0xCD
(PYMEM_CLEANBYTE
), frigjort minne fylls med bytena 0xDD
(PYMEM_DEADBYTE
). Minnesblock omges av ”förbjudna byte” som fylls med byte 0xFD
(PYMEM_FORBIDDENBYTE
). Strängar av dessa byte är sannolikt inte giltiga adresser, flyttal eller ASCII-strängar.
Kontroll av körtid:
Upptäck API-överträdelser. Detektera till exempel om
PyObject_Free()
anropas på ett minnesblock som allokerats avPyMem_Malloc()
.Detekterar skrivning före buffertens början (bufferten underflödar).
Detektera skrivning efter slutet av bufferten (buffer overflow).
Kontrollera att det finns en attached thread state när allokeringsfunktioner i domänerna
PYMEM_DOMAIN_OBJ
(ex:PyObject_Malloc()
) ochPYMEM_DOMAIN_MEM
(ex:PyMem_Malloc()
) anropas.
Vid fel använder debug-hooks modulen tracemalloc
för att få en spårning av var ett minnesblock allokerades. Spårningen visas bara om tracemalloc
spårar Python-minnesallokeringar och minnesblocket spårades.
Låt S = sizeof(size_t)
. 2*S
bytes läggs till i vardera änden av varje block om N bytes som begärs. Minneslayouten ser ut så här, där p representerar adressen som returneras av en malloc-liknande eller realloc-liknande funktion (p[i:j]
betyder byteskivan från *(p+i)
inklusive upp till *(p+j)
exklusive; observera att behandlingen av negativa index skiljer sig från en Python-skiva):
p[-2*S:-S]
Antal bytes som ursprungligen begärdes. Detta är en size_t, big-endian (lättare att läsa i en minnesdump).
p[-S]
API-identifierare (ASCII-tecken):
'r'
förPYMEM_DOMAIN_RAW
.'m'
förPYMEM_DOMAIN_MEM
.'o'
förPYMEM_DOMAIN_OBJ
.
p[-S+1:0]
Kopior av PYMEM_FORBIDDENBYTE. Används för att fånga upp underskrivna och underlästa filer.
p[0:N]
Det begärda minnet fylls med kopior av PYMEM_CLEANBYTE, som används för att fånga upp referenser till oinitialiserat minne. När en realloc-liknande funktion anropas och begär ett större minnesblock fylls även de nya överflödiga byte med PYMEM_CLEANBYTE. När en free-liknande funktion anropas skrivs dessa över med PYMEM_DEADBYTE, för att fånga referenser till frigjort minne. När en realloc-liknande funktion anropas och begär ett mindre minnesblock, fylls även de överflödiga gamla bytena med PYMEM_DEADBYTE.
p[N:N+S]
Kopior av PYMEM_FORBIDDENBYTE. Används för att fånga upp överskrivningar och läsningar.
p[N+S:N+2*S]
Används endast om makrot
PYMEM_DEBUG_SERIALNO
är definierat (inte definierat som standard).Ett serienummer som ökas med 1 vid varje anrop till en malloc-liknande eller realloc-liknande funktion. Big-endian
size_t
. Om ”dåligt minne” upptäcks senare är serienumret ett utmärkt sätt att sätta en brytpunkt vid nästa körning, för att fånga ögonblicket då detta block skickades ut. Den statiska funktionen bumpserialno() i obmalloc.c är det enda stället där serienumret ökas, och den finns för att du enkelt ska kunna sätta en sådan brytpunkt.
En realloc-liknande eller free-liknande funktion kontrollerar först att PYMEM_FORBIDDENBYTE-bytena i varje ände är intakta. Om de har ändrats skrivs en diagnostisk utdata till stderr och programmet avbryts via Py_FatalError(). Det andra huvudsakliga felet är att provocera fram ett minnesfel när ett program läser upp ett av de speciella bitmönstren och försöker använda det som en adress. Om du då går in i en debugger och tittar på objektet kommer du sannolikt att se att det är helt fyllt med PYMEM_DEADBYTE (vilket betyder att frigjort minne används) eller PYMEM_CLEANBYTE (vilket betyder att oinitialiserat minne används).
Ändrad i version 3.6: Funktionen PyMem_SetupDebugHooks()
fungerar nu även på Python som kompilerats i release-läge. Vid fel använder debuggkrokarna nu tracemalloc
för att få en spårning av var ett minnesblock allokerades. Felsöknings-hooks kontrollerar nu också om det finns en attached thread state när funktioner i domänerna PYMEM_DOMAIN_OBJ
och PYMEM_DOMAIN_MEM
anropas.
Ändrad i version 3.8: Bytemönstren 0xCB
(PYMEM_CLEANBYTE
), 0xDB
(PYMEM_DEADBYTE
) och 0xFB
(PYMEM_FORBIDDENBYTE
) har ersatts med 0xCD
, 0xDD
och 0xFD
för att använda samma värden som Windows CRT debug malloc()
och free()
.
Allokeringsverktyget pymalloc¶
Python har en pymalloc-allokering som är optimerad för små objekt (mindre eller lika med 512 byte) med kort livslängd. Den använder minnesmappningar som kallas ”arenor” med en fast storlek på antingen 256 KiB på 32-bitars plattformar eller 1 MiB på 64-bitars plattformar. Den faller tillbaka till PyMem_RawMalloc()
och PyMem_RawRealloc()
för allokeringar större än 512 byte.
pymalloc är standardallokering för domänerna PYMEM_DOMAIN_MEM
(ex: PyMem_Malloc()
) och PYMEM_DOMAIN_OBJ
(ex: PyObject_Malloc()
).
Arenaallokeringen använder sig av följande funktioner:
VirtualAlloc()
ochVirtualFree()
i Windows,mmap()
ochmunmap()
om tillgängliga,malloc()
ochfree()
annars.
Denna allokator inaktiveras om Python konfigureras med alternativet --without-pymalloc
. Den kan också inaktiveras under körning med hjälp av miljövariabeln PYTHONMALLOC
(ex: PYTHONMALLOC=malloc
).
Vanligtvis är det vettigt att inaktivera allokeringsverktyget pymalloc när man bygger Python med AddressSanitizer (--with-address-sanitizer
), vilket hjälper till att upptäcka lågnivåbuggar i C-koden.
Anpassa pymalloc Arena Allocator¶
Tillagd i version 3.4.
-
type PyObjectArenaAllocator¶
Struktur som används för att beskriva en arenaallokering. Strukturen har tre fält:
Fält
Betydelse
void *ctx
användarkontext som skickas som första argument
void* alloc(void *ctx, size_t size)
allokera en arena av storleken bytes
void free(void *ctx, void *ptr, size_t size)
frigöra en arena
-
void PyObject_GetArenaAllocator(PyObjectArenaAllocator *allocator)¶
Hämta arenans allokeringsenhet.
-
void PyObject_SetArenaAllocator(PyObjectArenaAllocator *allocator)¶
Ställ in arenaallokeringen.
Allokeringsverktyget mimalloc¶
Tillagd i version 3.13.
Python stöder allokatorn mimalloc när den underliggande plattformens stöd är tillgängligt. mimalloc ”är en allokator för allmänt ändamål med utmärkta prestandaegenskaper. Den utvecklades ursprungligen av Daan Leijen för körtidssystemen för språken Koka och Lean.”
tracemalloc C API¶
Tillagd i version 3.7.
-
int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size)¶
Spåra ett allokerat minnesblock i modulen
tracemalloc
.Returnera
0
vid framgång, returnera-1
vid fel (misslyckades med att allokera minne för att lagra spårningen). Returnerar-2
om tracemalloc är inaktiverat.Om minnesblocket redan är spårat, uppdatera den befintliga spårningen.
-
int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)¶
Ta bort spårningen av ett allokerat minnesblock i modulen
tracemalloc
. Gör ingenting om blocket inte spårades.Returnerar
-2
om tracemalloc är inaktiverat, annars returneras0
.
Exempel¶
Här är exemplet från avsnitt Översikt, omskrivet så att I/O-bufferten allokeras från Pythons heap med hjälp av den första funktionen set:
PyObject *res;
char *buf = (char *) PyMem_Malloc(BUFSIZ); /* för I/O */
om (buf == NULL)
return PyErr_NoMemory();
/* ...Gör någon I/O-operation som involverar buf... */
res = PyBytes_FromString(buf);
PyMem_Free(buf); /* allokerad med PyMem_Malloc */
returnera res;
Samma kod med hjälp av den typorienterade funktionen set:
PyObject *res;
char *buf = PyMem_New(char, BUFSIZ); /* för I/O */
if (buf == NULL)
return PyErr_NoMemory();
/* ...Gör någon I/O-operation som involverar buf... */
res = PyBytes_FromString(buf);
PyMem_Free(buf); /* allokeras med PyMem_New */
returnera res;
Observera att i de två exemplen ovan manipuleras bufferten alltid via funktioner som tillhör samma uppsättning. Det är faktiskt nödvändigt att använda samma minnes-API-familj för ett visst minnesblock, så att risken för att blanda olika allokatorer reduceras till ett minimum. Följande kodsekvens innehåller två fel, varav det ena är märkt som dödligt eftersom det blandar två olika allokatorer som arbetar på olika heaps.
char *buf1 = PyMem_New(char, BUFSIZ);
char *buf2 = (char *) malloc(BUFSIZ);
char *buf3 = (char *) PyMem_Malloc(BUFSIZ);
...
PyMem_Del(buf3); /* Fel -- borde vara PyMem_Free() */
free(buf2); /* Rätt -- allokerad via malloc() */
free(buf1); /* Fatalt -- bör vara PyMem_Free() */
Förutom de funktioner som syftar till att hantera råa minnesblock från Pythons heap allokeras och frigörs objekt i Python med PyObject_New
, PyObject_NewVar
och PyObject_Free()
.
Dessa kommer att förklaras i nästa kapitel om att definiera och implementera nya objekttyper i C.