[c++] Problema di stack overflow
Credo ormai abbiate capito che non sono un grandissimo esperto di programmazione ma sto cercando di fare un programmino anche se ogni tanto incappo in qualche errore.
Per esempio ho un programma che fa delle elaborazioni su una variabile e funziona perfettamente, appena ho implementato lo stesso per 3 variabili mi da erore e mi dice stack overflow. Mi sono un pò documentato e ho capito che praticamente satura la memoria di stack.
La soluzione che ho trovato sul web (alla mia portata), e inizializzare parte delle variabili con static in modo di allocare parte della memoria in global.
Giusto?
E' veramente brutto come modo di procedere?
Per esempio ho un programma che fa delle elaborazioni su una variabile e funziona perfettamente, appena ho implementato lo stesso per 3 variabili mi da erore e mi dice stack overflow. Mi sono un pò documentato e ho capito che praticamente satura la memoria di stack.
La soluzione che ho trovato sul web (alla mia portata), e inizializzare parte delle variabili con static in modo di allocare parte della memoria in global.
Giusto?
E' veramente brutto come modo di procedere?
Risposte
no cosi non mi funzionava bene, ora ho dichiarato quasi tutte le variabili in globale, cioè fuori dalla funzione e non mi da problemi.
Sono un macellaio??
Sono un macellaio??

Mostreresti il codice? Qual'era il tipo di queste variabili?
Non dichiarare come globali variabili che non lo sono, solo perché lo stack è troppo piccolo. Gli oggetti molto grossi normalmente si preferisce allocarli dinamicamente. Puoi inoltre aumentare le dimensione dello stack aggiungendo l'opzione del compilatore /F seguita dalla dimensione in Visual Studio.
Non dichiarare come globali variabili che non lo sono, solo perché lo stack è troppo piccolo. Gli oggetti molto grossi normalmente si preferisce allocarli dinamicamente. Puoi inoltre aumentare le dimensione dello stack aggiungendo l'opzione del compilatore /F seguita dalla dimensione in Visual Studio.
allora le variabili sono di tipo double e d_complex (dalla libreria CLN http://www.vni.com/products/imsl/docume ... ctions.htm).
Saranno una ventina di array da 16384 valori e altrettante variabili poco più piccole.
Dinamicamente quindi con la funzione malloc??
Ma cosa cambia da globale?
Saranno una ventina di array da 16384 valori e altrettante variabili poco più piccole.
Dinamicamente quindi con la funzione malloc??
Ma cosa cambia da globale?
Per lavorare con i numeri complessi in C++ puoi fare uso della classe template standard std::complex (http://stdcxx.apache.org/doc/stdlibug/20-2.html).
Ci sono grosse differenze tra dichiarare una variabile globale e allocare localmente gli array dinamicamente. La prima differenza riguarda la posizione in cui vengono allocati. Nel primo caso incidono sulla dimensione della tua applicazione, mentre nel secondo vengono allocati nell'heap. Quale sia il metodo migliore dipende molto da quale sia lo scopo della tua applicazione. Dovrebbero essere 128KB ad array e quindi un totale di 2.5MB. Non è tantissimo per gli attuali standard.
Una differenza più importante riguarda lo scope delle variabili. In un caso sono globali e accessibili da tutte le funzioni della tua applicazione, nel secondo caso solo nelle funzioni e classi che contengono un puntatore a quella memoria. Se ha senso che questi array siano accessibili globalmente, considerando la dimensione della tua applicazione, è perfettamente accettabile la scelta di dichiarare tutto globale. In caso contrario è normalmente preferibile utilizzare la memoria dinamica.
In C++ non si usa più malloc e free ma è preferibile usare gli operatori new e delete (new[] e delete[] per gli array).
Ci sono grosse differenze tra dichiarare una variabile globale e allocare localmente gli array dinamicamente. La prima differenza riguarda la posizione in cui vengono allocati. Nel primo caso incidono sulla dimensione della tua applicazione, mentre nel secondo vengono allocati nell'heap. Quale sia il metodo migliore dipende molto da quale sia lo scopo della tua applicazione. Dovrebbero essere 128KB ad array e quindi un totale di 2.5MB. Non è tantissimo per gli attuali standard.
Una differenza più importante riguarda lo scope delle variabili. In un caso sono globali e accessibili da tutte le funzioni della tua applicazione, nel secondo caso solo nelle funzioni e classi che contengono un puntatore a quella memoria. Se ha senso che questi array siano accessibili globalmente, considerando la dimensione della tua applicazione, è perfettamente accettabile la scelta di dichiarare tutto globale. In caso contrario è normalmente preferibile utilizzare la memoria dinamica.
In C++ non si usa più malloc e free ma è preferibile usare gli operatori new e delete (new[] e delete[] per gli array).
Bhè in realtà non hanno molto senso dichiarate globalmente perchè mi servono solo all'interno di una funzione. Ora mi studio bene new e delete e vediamo un pò che ne esce.
Per la grandezza dell'applicazione credo sia anche qualcosa di più mi pare stia sui 12MB.
Per la grandezza dell'applicazione credo sia anche qualcosa di più mi pare stia sui 12MB.
20 array di double di 16384 elementi sono 2.5MB, se ovviamente sono di tipi diversi la dimensione potrebbe essere maggiore. In ogni caso sulla dimensione dell'applicazione incidono molti altri fattori (c'è anche il codice della tua applicazione e di tutte le librerie che vengono linkate staticamente).
Puoi anche provare ad usare la classe std::vector.
Puoi anche provare ad usare la classe std::vector.
ok mi sto studiando l'operatore new e delete per allocare dinamicamente gli array ma ho un problema.
Praticamente l'array di valori double poi lo inserisco in una funzione che vuole come input un tipo double, e durante la compilazione mi da errore perchè riconosce l'array come un puntatore e non come un array double....come posso fare?
Ho postato solo il codice di interesse
Praticamente l'array di valori double poi lo inserisco in una funzione che vuole come input un tipo double, e durante la compilazione mi da errore perchè riconosce l'array come un puntatore e non come un array double....come posso fare?
double *com_accz; com_accz=new double [MAX_INT]; for(int i=0;i<MAX_INT;i++) { com_accz[i].re=accz[i]; com_accz[i].im=0.000000; } accfz = imsl_z_fft_complex(MAX_INT,com_accz, 0); delete [] com_accz;
Ho postato solo il codice di interesse
Ho guardato il prototipo della funzione... Il problema non è nell'uso di puntatori al posto di array (dal punto di vista della funzione le due cose sono equivalenti), ma nell'uso di double al posto di d_complex.
Il seguente dovrebbe funzionare
Il seguente dovrebbe funzionare
d_complex *com_accz = new d_complex[MAX_INT]; for (int i = 0; i < MAX_INT; i++) { com_accz[i].re=accz[i]; com_accz[i].im=0.000000; } accfz = imsl_z_fft_complex(MAX_INT, com_accz, 0); delete[] com_accz; free(accfz); // <- ricordati che devi anche deallocare questo array quando hai finito di usarlo...
Che stupido ero convinto che nel prototipo ci fosse un double...ok grazie ora provo
scusa ma qui mi da lo stesso problema:
freq_max è una variabile double. Se dichiaro x come double normale funziona
double *x=new double; //Crea le curve di ponderazione for(int i=0;i<=MAX_INT;i++) { x=i*freq_max/MAX_INT; weight_z[i] = imsl_d_cub_spline_value(x,ppz,0); } delete x;
freq_max è una variabile double. Se dichiaro x come double normale funziona
bha a quanto ho capito io questa tecnica di allocazione dinamica va benissimo sugli array invece non è il massimo per le variabili, perche se queste vengono usate da una funzione il programma da errore. Credo che la funzione in ogni caso lo veda come un puntatore, invece se è un array...mmm...array e puntatori sono parenti giusto?!
Ho scritto qualche tempo fa un lungo post sulle relazioni che ci sono tra puntatori ed array (dopo lo cerco e te lo posto). Quando ti ho detto di usare l'allocazione dinamica non volevo dire di usarla per qualsiasi cosa ma solo per gli array che usi. Insomma per le variabile che occupano più spazio Nel caso di una variabile double è meglio non farlo. Quando lavori con i puntatori lavori con un indirizzo di memoria e non con il valore della variabile a cui punti. Quindi per esempio se scrivi p + 1 con p array di double non sommi uno al valore double contenuto nella locazione di memoria a cui punti ma si sposta alla locazione di memoria successiva (nel senso al double successivo). Per modificare il double devi deferenziare il puntatore usando l'operatore * (l'operatore & è invece usato per ottenere un indirizzo):
double *x=new double; //Crea le curve di ponderazione for(int i=0;i<=MAX_INT;i++) { *x=i*freq_max/MAX_INT; weight_z[i] = imsl_d_cub_spline_value(*x,ppz,0); } delete x;
Ok grazie.
Per ora va bene cosi ho messo tutti gli array da 16384 valori double allocati dinamicamente quindi penso di aver fatto un buon lavoro, qualche variabile (i non array) rimasti li ho lasciati in globale e via.
Ma quanta memoria c'è nello heap che non ho capito? C'è un modo per vederlo?
Per ora va bene cosi ho messo tutti gli array da 16384 valori double allocati dinamicamente quindi penso di aver fatto un buon lavoro, qualche variabile (i non array) rimasti li ho lasciati in globale e via.
Ma quanta memoria c'è nello heap che non ho capito? C'è un modo per vederlo?
Era questa la discussione: http://www.matematicamente.it/forum/2-es-puntatori-t37018.html
Di memoria ne hai più o meno quanta è a disposizione sul tuo PC. Puoi allocare anche array molto grossi senza problemi (per esempio di qualche centinaia di MB). Non lasciarli in globale, sono locali alla funzione e quindi vanno allocati nello stack come immagino facessi all'inizio. Quindi semplicemente:
Di memoria ne hai più o meno quanta è a disposizione sul tuo PC. Puoi allocare anche array molto grossi senza problemi (per esempio di qualche centinaia di MB). Non lasciarli in globale, sono locali alla funzione e quindi vanno allocati nello stack come immagino facessi all'inizio. Quindi semplicemente:
{ double x; // qui usi la variabile } // qui ha cessato di esistere
Ho provato a rimettere tutte le variabili nella funzione ma ancora sono troppe e mi da sempre problemi di stack.
Provo a usare new anche su variabili non array vediamo se ci riesco
Provo a usare new anche su variabili non array vediamo se ci riesco
anche se ora non mi da come errore stack overflow ma :
Eccezione non gestita a 0x3fb05288 in unione.exe: 0xC0000005: Violazione di accesso nella lettura del percorso 0x3fb05288.
Eccezione non gestita a 0x3fb05288 in unione.exe: 0xC0000005: Violazione di accesso nella lettura del percorso 0x3fb05288.
Si tratta di un errore diverso con causa sicuramente molto diverse. Prova ad usare il debug in modo da capire in che funzione viene lanciata questa eccezione e scrivi il codice di quella funzione. Si tratta probabilmente in un errore nell'uso dei puntatori. Hai cercato di accedere oltre i limiti di qualche array secondo me.
si si esatto, avevo fatto un array troppo piccolo.
Ok ora ho messo quasi tutte le variabili nella funzione allocandole dinamicamente...finalmente sto capendo qualcosa di c++.
Sto anche capendo che la mia funzione è decisamente troppo grande e che potrei benissimo suddividerla in minimo 5-6 funzioni diverse. MA a parte l'ordine che potrei dare al programma posso avere dei benefici a suddividere la funzione in tante più piccole?
Ok ora ho messo quasi tutte le variabili nella funzione allocandole dinamicamente...finalmente sto capendo qualcosa di c++.
Sto anche capendo che la mia funzione è decisamente troppo grande e che potrei benissimo suddividerla in minimo 5-6 funzioni diverse. MA a parte l'ordine che potrei dare al programma posso avere dei benefici a suddividere la funzione in tante più piccole?
I vantaggi sono "solo" nella maggiore semplicità di gestione e manutenzione. D'altra parte se crescono troppo diventano poco gestibili. Quando si progetta un'applicazione si cerca di trovare il giusto compromesso tra numero di funzioni e loro lunghezza. In generale una funzione dovrebbe svolgere una singola operazione. Se nella tua funzione puoi "vedere" diverse parti allora può valer la pena di creare delle nuove funzioni.
ci sono una decina di parti diverse....ehehehhe.
Ma la memoria di stack è del programma o di ogni singola funzione?
Ma la memoria di stack è del programma o di ogni singola funzione?