Domanda Determina la dimensione della memoria allocata dinamicamente in C


C'è un modo in C per scoprire la dimensione della memoria allocata dinamicamente?

Ad esempio, dopo

char* p = malloc (100);

C'è un modo per scoprire la dimensione della memoria associata a p?


44
2017-08-15 11:21


origine


risposte:


Lista FAQ di comp.lang.c · Domanda 7.27 -

D. Così posso interrogare il malloc pacchetto per scoprire quanto è grande un blocco assegnato?

R. Sfortunatamente, non esiste un modo standard o portatile. (Alcuni compilatori forniscono estensioni non standard.) Se hai bisogno di sapere, dovrai tenerne traccia da solo. (Vedi anche domanda 7.28.)


37
2017-08-15 11:37



Non esiste un modo standard per trovare queste informazioni. Tuttavia, alcune implementazioni forniscono funzioni come msize per fare questo. Per esempio:

Tuttavia, tenere presente che malloc assegnerà un minimo della dimensione richiesta, pertanto è necessario verificare se la variante di msize per l'implementazione restituisce effettivamente la dimensione dell'oggetto o la memoria effettivamente allocata nell'heap.


38
2017-08-15 11:37



La mentalità C è quella di fornire al programmatore strumenti per aiutarlo nel suo lavoro, non per fornire astrazioni che cambino la natura del suo lavoro. C cerca anche di evitare di rendere le cose più facili / più sicure se ciò accade a spese del limite di prestazioni.

Alcune cose che ti piacerebbe fare con una regione di memoria richiedono solo la posizione dell'inizio della regione. Tali cose includono lavorare con stringhe con terminazione nulla, manipolando il primo n byte della regione (se la regione è nota per essere almeno così grande), e così via.

Fondamentalmente, tenere traccia della lunghezza di una regione è un lavoro extra, e se C lo ha fatto automaticamente, a volte lo farebbe inutilmente.

Molte funzioni di libreria (ad esempio fread()) richiedono un puntatore all'inizio di una regione e anche la dimensione di questa regione. Se hai bisogno della dimensione di una regione, devi tenerne traccia.

Sì, le implementazioni di malloc () di solito tengono traccia delle dimensioni di una regione, ma possono farlo indirettamente, o arrotondare a un valore o non tenerle affatto. Anche se lo supportano, trovare le dimensioni in questo modo potrebbe essere lento rispetto a tenerne traccia da solo.

Se hai bisogno di una struttura dati che sappia quanto sia grande ogni regione, C può farlo per te. Basta usare una struttura che tenga traccia di quanto è grande la regione e di un puntatore alla regione.


8
2017-08-15 12:46



No, la libreria runtime C non fornisce questa funzione.

Alcune librerie possono fornire funzioni specifiche della piattaforma o del compilatore che possono ottenere queste informazioni, ma generalmente il modo per tenere traccia di queste informazioni è in un'altra variabile intera.


6
2017-08-15 11:25



Come tutti gli altri hanno già detto: No, non c'è.

Inoltre, eviterei sempre tutte le funzioni specifiche del venditore qui, perché quando trovi che hai davvero bisogno di usarle, è generalmente un segno che stai sbagliando. Si dovrebbe o memorizzare la dimensione separatamente, o non doverlo sapere affatto. L'utilizzo delle funzioni del venditore è il modo più rapido per perdere uno dei principali vantaggi della scrittura in C, portabilità.


3
2017-08-15 12:32



Mi aspetto che questo dipenda dall'implementazione.
Se hai la struttura dei dati dell'intestazione, puoi ridistribuirla sul puntatore e ottenere la dimensione.


2
2017-08-15 11:25



Questo codice probabilmente funzionerà sulla maggior parte delle installazioni di Windows:

template <class T>
int get_allocated_bytes(T* ptr)
{
 return *((int*)ptr-4);
}

template <class T>
int get_allocated_elements(T* ptr)
{
 return get_allocated_bytes(ptr)/sizeof(T);
}

2
2017-10-31 14:50



Ecco il modo migliore che ho visto per creare un puntatore taggato per memorizzare le dimensioni con l'indirizzo. Tutte le funzioni del puntatore continuerebbero a funzionare come previsto:

Trafugato da: https://stackoverflow.com/a/35326444/638848

È inoltre possibile implementare un wrapper per malloc e aggiungere tag gratuiti   (come le dimensioni allocate e altre metamodifiche) prima del puntatore   restituito da malloc. Questo è in effetti il ​​metodo che un compilatore c ++   etichetta oggetti con riferimenti a classi virtuali. Qui c'è uno che funziona   esempio:

#include <stdlib.h>
#include <stdio.h>

void * my_malloc(size_t s) 
{
  size_t * ret = malloc(sizeof(size_t) + s);
  *ret = s;
  return &ret[1];
}

void my_free(void * ptr) 
{
  free( (size_t*)ptr - 1);
}

size_t allocated_size(void * ptr) 
{
  return ((size_t*)ptr)[-1];
}

int main(int argc, const char ** argv) {
  int * array = my_malloc(sizeof(int) * 3);
  printf("%u\n", allocated_size(array));
  my_free(array);
  return 0;
}

Il vantaggio di questo metodo su una struttura con dimensioni e puntatore

 struct pointer
 {
   size_t size;
   void *p;
 };

è che hai solo bisogno di sostituire il malloc e le chiamate gratuite. Tutti   le altre operazioni del puntatore non richiedono alcun refactoring.


2
2018-04-20 05:02



No, non c'è.


1
2017-08-15 11:26



Se usi malloc, non puoi ottenere la taglia.

D'altra parte, se si utilizza OS API per allocare dinamicamente la memoria, come Windows funzioni heap, quindi è possibile farlo.


1
2017-08-15 11:36



Questo potrebbe funzionare, un piccolo aggiornamento nel tuo codice:

void* inc = (void*) (++p)
size=p-inc;

Ma ciò comporterà 1, cioè la memoria associata a p se è char*. Se è int* allora il risultato sarà 4.

Non c'è modo di scoprire l'allocazione totale.


1
2017-07-29 08:02