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
}
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). –
Congratulazioni per ottenere quattro voti per la prima domanda. Ci auguriamo che il tuo soggiorno a StackOverflow sia piacevole. – Almo
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 ... –