Come posso ottenere la dimensione di un blocco di memoria allocato usando malloc ()?

Possibili duplicati:
Come posso ottenere la dimensione di un array da un puntatore in C?
C’è un modo per determinare la dimensione di un array C ++ a livello di programmazione? E se no, perché?

Ottengo un puntatore a un blocco di memoria allocata da una funzione in stile C. Ora, sarebbe davvero interessante per scopi di debug sapere quanto è grande il blocco di memoria assegnato che questo puntatore punta.

C’è qualcosa di più elegante che provocare un’eccezione correndo ciecamente oltre i suoi confini?

Grazie in anticipo, Andreas

MODIFICARE:

Uso VC ++ 2005 su Windows e GCC 4.3 su Linux

EDIT2:

Ho _msize sotto VC ++ 2005 Purtroppo si traduce in un’eccezione in modalità di debug ….

Edit3:

Bene. Ho provato il modo in cui ho descritto sopra con l’eccezione, e funziona. Almeno mentre eseguo il debug e mi assicuro che subito dopo che la chiamata alla libreria sia terminata, eseguo i limiti del buffer. Funziona come un fascino.

Semplicemente non è elegante e in nessun modo utilizzabile nel codice di produzione.

    Non è standard ma se la tua libreria ha una funzione msize () che ti darà la dimensione.

    Una soluzione comune è avvolgere malloc con la propria funzione che registra ogni richiesta insieme alle dimensioni e all’intervallo di memoria risultante, nella build di rilascio è ansible tornare al malloc “reale”.

    Se non ti dispiace la violenza sleazy per il debugging, puoi #define i macro per agganciare le chiamate a malloc e liberare e riempire i primi 4 byte con le dimensioni.

    Per la musica di

     void *malloc_hook(size_t size) { size += sizeof (size_t); void *ptr = malloc(size); *(size_t *) ptr = size; return ((size_t *) ptr) + 1; } void free_hook (void *ptr) { ptr = (void *) (((size_t *) ptr) - 1); free(ptr); } size_t report_size(ptr) { return * (((size_t *) ptr) - 1); } 

    poi

     #define malloc(x) malloc_hook(x) 

    e così via

    La libreria runtime C non fornisce questa funzione. Inoltre, provocare deliberatamente un’eccezione non ti dirà quanto sia grande il blocco.

    Solitamente il modo in cui questo problema viene risolto in C è quello di mantenere una variabile separata che tenga traccia delle dimensioni del blocco assegnato. Certo, questo a volte è inopportuno, ma in genere non c’è altro modo per saperlo.

    La tua libreria runtime C può fornire alcune funzioni di debug dell’heap in grado di interrogare i blocchi allocati (dopo tutto, free() deve sapere quanto è grande il blocco), ma qualsiasi tipo di cosa sarà non portabile.

    Con gcc e il GNU linker , puoi facilmente avvolgere malloc

     #include  #include  void* __real_malloc(size_t sz); void* __wrap_malloc(size_t sz) { void *ptr; ptr = __real_malloc(sz); fprintf(stderr, "malloc of size %d yields pointer %p\n", sz, ptr); /* if you wish to save the pointer and the size to a data structure, then remember to add wrap code for calloc, realloc and free */ return ptr; } int main() { char *x; x = malloc(103); return 0; } 

    e compilare con

     gcc ac -oa -Wall -Werror -Wl,--wrap=malloc 

    (Naturalmente, questo funzionerà anche con codice c ++ compilato con g ++ e con il nuovo operatore (tramite il suo nome mutilato), se lo si desidera.)

    In effetti, la libreria caricata staticamente / dynamicmente utilizzerà anche __wrap_malloc .

    No, e non è ansible fare affidamento su un’eccezione quando si superano i suoi limiti, a meno che non sia nella documentazione della tua implementazione. Fa parte delle cose di cui non hai davvero bisogno di sapere per scrivere programmi. Scava nella documentazione del compilatore o nel codice sorgente se vuoi davvero saperlo.

    Non esiste una funzione C standard per farlo. A seconda della piattaforma, potrebbe esserci un metodo non portatile: quale libreria OS e C stai usando?

    Nota che provocare un’eccezione è inaffidabile: potrebbero esserci altre allocazioni immediatamente dopo il chunk che hai, e quindi potresti non ottenere un’eccezione fino a molto tempo dopo aver superato i limiti del tuo attuale chunk.

    I controller di memoria come il memcheck di Valgrind e il TCMalloc di Google (la parte del controllo dell’heap) tengono traccia di questo genere di cose.

    È ansible utilizzare TCMalloc per eseguire il dump di un profilo dell’heap che mostra dove sono state allocate le cose oppure è sufficiente controllarlo per assicurarsi che l’heap sia lo stesso in due punti nell’esecuzione del programma utilizzando SameHeap () .

    Soluzione parziale: su Windows è ansible utilizzare PageHeap per catturare un accesso alla memoria al di fuori del blocco assegnato.

    PageHeap è un gestore di memoria alternativo presente nel kernel di Windows (nelle varietà NT ma nessuno dovrebbe usare qualsiasi altra versione al giorno d’oggi). Prende ogni allocazione in un processo e restituisce un blocco di memoria che ha la sua fine allineata con la fine di una pagina di memoria, quindi rende inaccessibile la pagina seguente (nessuna lettura, nessun accesso in scrittura). Se il programma tenta di leggere o scrivere oltre la fine del blocco, otterrai una violazione di accesso che puoi catturare con il tuo debugger preferito.

    Come ottenerlo: scaricare e installare il pacchetto Strumenti di debug per Windows da Microsoft: http://www.microsoft.com/whdc/devtools/debugging/default.mspx

    quindi lancia l’utility GFlags, vai alla terza scheda e inserisci il nome del tuo eseguibile, quindi premi il tasto. Seleziona la casella di controllo PageHeap, fai clic su OK e sei a posto.

    L’ultima cosa: quando hai finito con il debug, non dimenticarti mai di lanciare nuovamente GFlags e disabilitare PageHeap per l’applicazione. GFlags immette questa impostazione nel Registro di sistema (in HKLM \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Opzioni di esecuzione file di immagine \), quindi è persistente, anche attraverso i riavvii.

    Inoltre, tieni presente che l’utilizzo di PageHeap può aumentare enormemente le esigenze di memoria della tua applicazione.

    Il modo di fare ciò che vuoi è ESSERE l’allocatore. Se si filtrano tutte le richieste e quindi le si registra a scopo di debug, è ansible scoprire ciò che si desidera quando la memoria è libera.

    Inoltre, è ansible controllare alla fine del programma per vedere se tutti i blocchi allocati sono stati liberati e, in caso contrario, elencarli. Una libreria ambiziosa di questo tipo potrebbe persino utilizzare i parametri FUNCTION e LINE tramite una macro per farti sapere esattamente dove stai perdendo memoria.

    Infine, MSVCRT di Microsoft fornisce un heap debuggabile con molti strumenti utili che è ansible utilizzare nella versione di debug per individuare problemi di memoria: http://msdn.microsoft.com/en-us/library/bebs9zyz.aspx

    Su Linux, puoi usare valgrind per trovare molti errori. http://valgrind.org/