Come posso ottenere la dimensione di un blocco di memoria allocata usando malloc ()? [duplicare]

StackOverflow https://stackoverflow.com/questions/1208644

Domanda

  

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 codice? E se no, perché?

Ottengo un puntatore a un pezzo di memoria allocata da una funzione in stile C. Ora, sarebbe davvero interessante per scopi di debug sapere come grande il blocco di memoria allocato che indica questo puntatore.

Esiste qualcosa di più elegante che provocare un'eccezione attraversando ciecamente i suoi confini?

Grazie in anticipo, Andreas

EDIT:

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

EDIT2:

Ho _msize in VC ++ 2005 Purtroppo si traduce in un'eccezione in modalità debug ....

Edit3:

Bene. Ho provato il modo sopra descritto con l'eccezione, e funziona. Almeno mentre sto eseguendo il debug e assicurandomi immediatamente dopo la chiamata alle uscite della libreria corro oltre i limiti del buffer. Funziona come un fascino.

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

È stato utile?

Soluzione

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

Una soluzione comune è quella di racchiudere malloc con la propria funzione che registra ogni richiesta insieme alle dimensioni e all'intervallo di memoria risultante, nella build di rilascio è possibile tornare al "reale" malloc .

Altri suggerimenti

Se non ti dispiace la violenza squallida per motivi di debug, puoi #definire le macro per agganciare le chiamate a malloc e liberare e riempire i primi 4 byte con le dimensioni.

Al ritmo 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);
}

quindi

#define malloc(x) malloc_hook(x)

e così via

La libreria di runtime C non fornisce tale funzione. Inoltre, provocare deliberatamente un'eccezione non ti dirà nemmeno quanto è grande il blocco.

Di solito il modo in cui questo problema viene risolto in C è quello di mantenere una variabile separata che tiene traccia della dimensione del blocco allocato. Certo, questo a volte è scomodo ma generalmente non c'è altro modo di saperlo.

La tua libreria di runtime C potrebbe fornire alcune funzioni di debug dell'heap che possono interrogare i blocchi allocati (dopo tutto, free () deve sapere quanto è grande il blocco), ma qualsiasi cosa di questo genere sarà non portabile.

Con gcc e il linker GNU , puoi facilmente avvolgere malloc

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


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 compila con

gcc a.c -o a -Wall -Werror -Wl,--wrap=malloc

(Naturalmente, questo funzionerà anche con il codice c ++ compilato con g ++, e con il nuovo operatore (attraverso il suo nome alterato) se lo desideri.)

In effetti, la libreria caricata staticamente / dinamicamente utilizzerà anche il tuo __wrap_malloc .

No, e non puoi 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 che davvero non devi sapere per scrivere programmi. Scava nella documentazione del compilatore o nel codice sorgente se vuoi davvero saperlo.

Non esiste una funzione C standard per eseguire questa operazione. A seconda della tua piattaforma, potrebbe esserci un metodo non portatile: quale libreria di sistema operativo e C stai usando?

Nota che provocare un'eccezione non è affidabile - potrebbero esserci altre allocazioni immediatamente dopo il blocco che hai, e quindi potresti non ottenere un'eccezione fino a quando non superi i limiti del tuo blocco corrente.

Controlli della memoria come Memcheck di Valgrind e TCMalloc di Google (la parte del controllo heap) tiene traccia di questo genere di cose.

Puoi usare TCMalloc per scaricare un profilo di heap che mostra dove sono state allocate le cose, oppure puoi semplicemente controllarlo per assicurarti che il tuo heap sia lo stesso in due punti nell'esecuzione del programma usando SameHeap () .

Soluzione parziale: su Windows puoi usare PageHeap per catturare un accesso alla memoria al di fuori del blocco allocato.

PageHeap è un gestore di memoria alternativo presente nel kernel di Windows (nelle varietà NT ma nessuno dovrebbe usare nessuna 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 prova a leggere o scrivere oltre la fine del blocco, otterrai una violazione di accesso che puoi rilevare con il tuo debugger preferito.

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

quindi avvia l'utilità 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: una volta terminato il debug, non dimenticare di riavviare GFlags e disabilitare PageHeap per l'applicazione. GFlags inserisce questa impostazione nel Registro di sistema (in HKLM \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Opzioni di esecuzione file 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 per fare ciò che vuoi è ESSERE l'allocatore. Se si filtrano tutte le richieste e le si registra per scopi di debug, è possibile scoprire cosa si desidera quando la memoria è libera.

Inoltre, puoi 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 accettare i parametri FUNZIONE e LINE tramite una macro per farti sapere esattamente dove stai perdendo memoria.

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

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top