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().

Se Memory Allocation APIs.

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 om PyMem_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 om PyMem_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 anropet PyMem_RawMalloc(n); om n är lika med noll ändras minnesblockets storlek men det frigörs inte och den returnerade pekaren är inte NULL.

Om inte p är NULL måste den ha returnerats av ett tidigare anrop till PyMem_RawMalloc(), PyMem_RawRealloc() eller PyMem_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() eller PyMem_RawCalloc(). Annars, eller om PyMem_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 om PyMem_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 om PyMem_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 anropet PyMem_Malloc(n); om n är lika med noll ändras minnesblockets storlek men det frigörs inte och den returnerade pekaren är inte NULL.

Om inte p är NULL måste den ha returnerats av ett tidigare anrop till PyMem_Malloc(), PyMem_Realloc() eller PyMem_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() eller PyMem_Calloc(). Annars, eller om PyMem_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 till TYPE*. 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 till TYPE*. Vid retur kommer p att vara en pekare till det nya minnesområdet, eller NULL 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 om PyObject_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 om PyObject_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 anropet PyObject_Malloc(n); om n är lika med noll ändras minnesblockets storlek men det frigörs inte och den returnerade pekaren är inte NULL.

Om inte p är NULL måste den ha returnerats av ett tidigare anrop till PyObject_Malloc(), PyObject_Realloc() eller PyObject_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() eller PyObject_Calloc(). Annars, eller om PyObject_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 eller PyObject_GC_NewVar; använd istället PyObject_GC_Del().

Se även

Standard minnesallokatorer

Standardminnesallokatorer:

Konfiguration

Namn

PyMem_RawMalloc

PyMem_Malloc

PyObject_Malloc

Release-version

"pymalloc"

malloc

pymalloc

pymalloc

Felsök byggnaden

"pymalloc_debug"

malloc + felsökning

pymalloc + felsökning

pymalloc + felsökning

Release-version, utan pymalloc

"malloc"

malloc

malloc

malloc

Felsökning, utan pymalloc

"malloc_debug"

malloc + felsökning

malloc + felsökning

malloc + felsökning

Legend:

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 till PyMemAllocatorEx och ett nytt fält calloc 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:

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öre Py_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:

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):

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() och VirtualFree() i Windows,

  • mmap() och munmap() om tillgängliga,

  • malloc() och free() 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 returneras 0.

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.