2015-11-17 19 views
5

Volevo un buffer allocato comune ad una classe (da utilizzare come scratchpad durante i calcoli). A un certo punto posso liberare e quindi riallocare il buffer se non è abbastanza grande. Volevo che il buffer esistesse senza dover chiamare un "myclass :: initialize();" in main(); Ho trovato il seguente codice che compila e funziona bene per il mio scopo.Malloc al di fuori di main() o qualsiasi altra funzione (vale a dire a livello globale)

Le mie domande sono: Perché questo codice viene compilato correttamente? Perché malloc() può essere al di fuori di main() o di qualsiasi altra funzione? Il compilatore sta interpretando questo in qualche modo e rimuovendo il malloc?

codice compilato su linux 64bit con "g ++ example.cpp" e controllata con valgrind

// example.cpp 
#include <cstdio> 
#include <cstdlib> 

class myclass { 
public: 
    static char* pbuf;      // buffer 
    static unsigned int length;   // buffer length 
    const static unsigned int chunk_size; // allocation chunck size 
}; 

// set constants and allocate buffer 
const unsigned int myclass::chunk_size = sizeof(long unsigned int) * 8; 
unsigned int myclass::length = chunk_size; // start with smallest chunk 
char* myclass::pbuf = (char*)malloc(sizeof(char)*myclass::length); 

int main() { 

    // write to buffer (0 to 63 on 64bit machine) 
    for (int i = 0; i < myclass::length; i++) { 
     *(myclass::pbuf+i) = i; 
    } 

    // read from buffer (print the numbers 0 to 63) 
    for (int i = 0; i < myclass::length; i++) { 
    printf("%d\n", *(myclass::pbuf+i)); 
    } 

    free(myclass::pbuf); // last line of program 
} 

Grazie per le risposte. Sembra che questo sia più comune di quanto pensassi. "Le chiamate alle funzioni sono consentite negli inizializzatori statici". Questo mi porta a una versione leggermente modificata la cattura di un possibile errore di malloc:

#include <cstdio> 
#include <cstdlib> 

class myclass { 
public: 
    static char* pbuf;      // buffer 
    static unsigned int length;   // buffer length 
    const static unsigned int chunk_size; // allocation chunck size 
    static void* malloc_buf(unsigned int); 
}; 

// set constants and allocate buffer 
const unsigned int myclass::chunk_size = sizeof(long unsigned int) * 8; 
unsigned int myclass::length = chunk_size; // start with smallest chunk 
//char* myclass::pbuf = (char*)malloc(sizeof(char)*myclass::length); 
char* myclass::pbuf = (char*)myclass::malloc_buf(sizeof(char)*myclass::length); 

void* myclass::malloc_buf(unsigned int N) { 
    void* buf = malloc(N); 
    if (!buf) exit(EXIT_FAILURE); 
    return buf; 
} 

int main() { 

    // write to buffer (0 to 63 on 64bit machine) 
    for (int i = 0; i < myclass::length; i++) { 
     *(myclass::pbuf+i) = i; 
    } 

    // read from buffer (print the numbers 0 to 63) 
    for (int i = 0; i < myclass::length; i++) { 
    printf("%d\n", *(myclass::pbuf+i)); 
    } 

    free(myclass::pbuf); // last line of program 
} 
+2

Questa è una cosa estremamente pericolosa da fare. Se qualsiasi altro inizializzatore statico in una diversa unità di compilazione accede a 'pbuf', i risultati sono imprevedibili e potrebbero variare su diversi compilatori, piattaforme e persino compilazioni dello stesso codice con lo stesso compilatore. Vedi [fiasco dell'ordine statico] (http://stackoverflow.com/questions/tagged/static-order-fiasco). –

+0

Congratulazioni per ottenere quattro voti per la prima domanda. Ci auguriamo che il tuo soggiorno a StackOverflow sia piacevole. – Almo

+0

Il codice di esempio in main() è fuorviante (scuse). In realtà le funzioni dei membri della classe sono le uniche che accedono ai dati pbuf. Ho definito il buffer un "blockpad" nella mia mente. L'idea è che una funzione membro possa utilizzare il buffer scratchpad disponibile poiché è "disponibile" e "abbastanza grande". Se è troppo piccolo, esiste una funzione per ridimensionarlo, ma rimane "grande" per tutto il tempo necessario. L'idea è che ho appena lasciato il buffer in modo che le funzioni membro abbiano un'area temporanea da usare ... –

risposta

2

Sta solo facendo inizializzazione statico (inizializzazione prima principale si chiama). Gli inizializzatori statici sono autorizzati a chiamare le funzioni.

+0

Non è proprio l'inizializzazione dinamica? Intendo l'inizializzazione della variabile pbuf. Come si può conoscere il valore di ritorno di malloc al momento della compilazione? –

+0

Confesso che non sono chiaro sulla terminologia. Sta inizializzando una variabile 'static' ma mi rendo conto che ci sono molti modi in cui ciò accade. Sembra che le persone si riferiscano vagamente a tutte quelle come "inizializzazione statica" dal momento che stanno inizializzando le variabili statiche ma se questo è tecnicamente corretto o meno non potrei dire. –

+0

Sì, @ JorgeGonzálezLorenzo sembra essere corretto: http://en.cppreference.com/w/cpp/language/initialization Penso che la maggior parte delle persone si riferisca vagamente a qualsiasi cosa che inizializzi le variabili statiche come "inizializzazione statica" ma penso che sia non tecnicamente corretto qui. –

1

main() è solo un'altra funzione, che è il motivo per cui sono stati inseriti requisiti specifici per consentirne il corretto richiamo.

Altre cose possono accadere prima che venga chiamato. Inizializzazione statica tra di loro.

Problemi correlati