2010-04-28 12 views
8

gcc 4.4.1 c89Uso sizeof con un array allocato dinamicamente

ho il seguente frammento di codice:

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

char *buffer = malloc(10240); 
/* Check for memory error */ 
if(!buffer) 
{ 
    fprintf(stderr, "Memory error\n"); 
    return 1; 
} 
printf("sizeof(buffer) [ %d ]\n", sizeof(buffer)); 

Tuttavia, il sizeof (buffer) sempre stampato 4. So che un char * è solo 4 byte. Tuttavia, ho assegnato la memoria per 10kb. Quindi la dimensione non dovrebbe essere 10240? Mi sto chiedendo sto pensando proprio qui?

Molte grazie per qualsiasi suggerimento,

+2

Per la maggior parte, il compilatore C (per qualsiasi versione) non ha idea di cosa sia la funzione 'malloc' per la quale è stata o utilizzata. Tutto quello che sa è che richiede un intero senza segno (size_t) e restituisce un puntatore void. Potrebbe usare il suo parametro per seminare il generatore di numeri casuali e lanciare un numero casuale su un '(void *)' per tutte le preoccupazioni del compilatore, quindi il compilatore non può sapere quale sia la dimensione della memoria puntata. – nategoose

risposta

14

Si sta richiedendo la dimensione di un char* che è 4 infatti, non la dimensione del buffer. L'operatore sizeof non può restituire la dimensione di un buffer assegnato dinamicamente, solo la dimensione dei tipi statici e delle strutture note in fase di compilazione.

+2

'sizeof' può restituire la dimensione di un buffer dinamico per matrici di lunghezza variabile in C99. –

+0

C'è qualche metodo sotto c89 che puoi trovare quanta memoria è stata allocata con un buffer allocato dinamicamente? Grazie. – ant2009

+2

@Carl - Gli VLA non sono dinamici. Sono "a lunghezza variabile" in quanto la loro lunghezza può essere calcolata in fase di esecuzione, ma non "lunghezza variabile" in quanto la loro lunghezza può cambiare. Sono ancora array basati su stack, motivo per cui 'sizeof' è definito per funzionare per loro. –

9

sizeof non funziona su allocazioni dinamiche (con alcune eccezioni in C99). Il tuo uso di sizeof qui ti dà solo la dimensione del puntatore. Questo codice vi darà il risultato desiderato:

char buffer[10240]; 
printf("sizeof(buffer) [ %d ]\n", sizeof(buffer)); 

Se malloc() riesce, la memoria indicò è almeno grande come lei ha chiesto, quindi non c'è alcun motivo di preoccuparsi del reale dimensioni esso assegnato.

Inoltre, hai assegnato 10 kB, non 1 kB.

+0

Questo codice è più che un po 'pericoloso: sta allocando il buffer sullo stack, non l'heap. Se si lascia fuoriuscire qualsiasi puntatore a questo buffer dalla funzione che lo dichiara, si è in procinto di impilare la corruzione (e in base alla durata dell'esecuzione del programma, al danneggiamento dell'heap e/o a un errore di segmentazione). – Anon

+2

@Anon - Non è pericoloso, risolve il problema in modo diverso. L'OP non aveva requisiti per il trasferimento del buffer da una funzione. –

+0

E qual è, esattamente, il problema dell'OP?Mi sembra che stia tenendo traccia delle dimensioni di una struttura allocata all'heap. Suggerire che l'OP usi una struttura allocata nello stack non è una soluzione a questo problema. – Anon

3

Spetta a te tenere traccia delle dimensioni della memoria se necessario. La memoria restituita da malloc è solo un puntatore ai dati "non inizializzati". L'operatore sizeof lavora solo sulla variabile buffer.

+0

Sicuramente l'ambiente runtime conosce la dimensione del buffer allocato (perché 'free (void *)' non richiede la dimensione), quindi perché dovremmo tenerne traccia da soli? – Dai

+0

Il codice di gestione della memoria sottostante ha quasi sicuramente le dimensioni, a meno che non abbia qualche algoritmo magico per liberare ciò che non richiede dimensioni. Ma quell'informazione non è esposta. –

+0

C'è un motivo per cui i dati non vengono esposti? – Dai

2

Sostituire sizeof per malloc_usable_size (la pagina di manuale indica che questo non è portabile, quindi potrebbe non essere disponibile con la specifica implementazione C).

+1

'malloc_usable_size()' è molto non portatile. Non ce l'ho su OS X Leopard. Ad ogni modo, affidarsi ad esso è una pessima idea in primo luogo (come indicato anche nella manpage). –

+0

NOTA: se non ti interessa la portabilità e sei su OSX (o qualcun altro non se ne preoccupa e sei bloccato con il porting su OSX) malloc_size da è il tuo uomo per il lavoro. – Stripes

3

No. buffer è un char *. È un puntatore ai dati char. Il puntatore occupa solo 4 byte (sul tuo sistema).

Punta a 10240 byte di dati (che, a proposito, non è 1Kb. Più simile a 10Kb), ma il puntatore non sa che. Prendere in considerazione:

int a1[3] = {0, 1, 2}; 
int a2[5] = {0, 1, 2, 3, 4}; 

int *p = a1; 
// sizeof a1 == 12 (3 * sizeof(int)) 
// but sizeof p == 4 
p = a2 
// sizeof a2 == 20 
// sizeof p still == 4 

È la differenza principale tra gli array e i puntatori. Se non funzionasse in questo modo, sizeof p cambierebbe nel codice precedente, il che non ha senso per una costante in fase di compilazione.