PDA

View Full Version : [C] Allocazione/Deallocazione memoria


nico88desmo
21-10-2011, 11:44
Un saluto a tutti.

Avrei un dubbio sul funzionamento del seguente codice sorgente


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

typedef struct _prova {
long *c;
char *s;
} prova;


int main() {
char wait;

printf("creo");
scanf("%c",&wait);
prova *p = malloc(sizeof(prova)*1000000);

int i=0;
for (; i<1000000; i++){
p[i].c=malloc(sizeof(long));
p[i].s=malloc(sizeof(char)*10);
}

printf("creato");
scanf("%c",&wait);
for (i = 0; i<1000000; i++){
free(p[i].c);
free(p[i].s);
}
free(p);
printf("eliminato");
scanf("%c",&wait);
}


In pratica creo un vettore di elementi di tipo prova, alloco ciascun elemento e infine li dealloco tutti.

Il problema e' il seguente: guardando il processo associato al sorgente nel task manager, nonostante l'eliminazione di tutto il vettore, vedo che al processo e' associata parecchia memoria (come se la free non funzionasse);
Qualcuno saprebbe spiegarmi il motivo?

Grazie

tecno789
22-10-2011, 17:16
Il problema e' il seguente: guardando il processo associato al sorgente nel task manager, nonostante l'eliminazione di tutto il vettore, vedo che al processo e' associata parecchia memoria (come se la free non funzionasse);
Qualcuno saprebbe spiegarmi il motivo?

Grazie[/QUOTE]

prova con la fflush()

Freaxxx
22-10-2011, 17:43
provato con Codeblocks 10.05 sotto Windows 7 professional 32 bit ed il processo occupa pochi kb dopo il messaggio di eliminazione del vettore.

Floris
22-10-2011, 17:53
Se Freaxxx ha ragione, allora può essere che Windows non liberi le pagine occupate dal processo ma non più utilizzate.

Freaxxx
22-10-2011, 17:57
per inciso l'ho provato su una macchina con AMD C50, ovvero una macchina con CPU e Northbridge ( e GPU ) integrati in un solo package, quindi il controller di memoria è integrato nel DIE della CPU, i tempi di accesso in memoria sono particolarmente brevi con queste nuove APU/CPU, magari tu lo provi su una piattaforma con controller di memoria esterno e montato sulla scheda madre.

demos88
22-10-2011, 18:05
per inciso l'ho provato su una macchina con AMD C50, ovvero una macchina con CPU e Northbridge ( e GPU ) integrati in un solo package, quindi il controller di memoria è integrato nel DIE della CPU, i tempi di accesso in memoria sono particolarmente brevi con queste nuove APU/CPU, magari tu lo provi su una piattaforma con controller di memoria esterno e montato sulla scheda madre.
si parlerebbe cmq di una differenza dell'ordine dei nanosecondi...
Penso dipenda dal sistema operativo e dal modo in cui alloca (e dealloca) memoria ai programmi. Ma potrebbe dipendere anche dall'ambiente di sviluppo...

Freaxxx
22-10-2011, 18:08
si parlerebbe cmq di una differenza dell'ordine dei nanosecondi...
Penso dipenda dal sistema operativo e dal modo in cui alloca (e dealloca) memoria ai programmi. Ma potrebbe dipendere anche dall'ambiente di sviluppo...

in linea teorica si, ma assumendo per vero il fatto che passi per la scheda madre, c'è anche da includere come possibili variabili le prestazioni dei driver del chipset della scheda madre.

demos88
22-10-2011, 18:26
in linea teorica si, ma assumendo per vero il fatto che passi per la scheda madre, c'è anche da includere come possibili variabili le prestazioni dei driver del chipset della scheda madre.
capisco, ma di fatto la gestione della memoria è affidata al kernel dell'OS.
L'hardware è a disposizione diretta del sistema operativo, tratta i dati per quel che sono e non si preoccupa di altro.
Quello che ti dice "gli indirizzi di memoria da 0x00000 a 0x000FF sono allocati" non è l'hardware, ma l'OS. Se l'OS invia un comando di dealloc, quell'area di memoria verrà in ogni caso liberata con una serie di istruzioni che la macchina esegue ad occhi chiusi e l'OS considera quell'area di memoria vuota e quindi non allocata, e anche se l'hardware non l'avesse liberata (penso che tra l'altro l'hardware non faccia niente) non importa, sarà marcata libera.
Le istruzioni di deallocazione sono corrette, probabilmente l'ambiente di sviluppo le tiene allocate perchè magari è in qualche particolare forma di debug.
Quello che voglio dire è che driver, hardware, bios ecc... possono certamente influenzare la velocità di allocazione e deallocazione, ma deallocare 22mB (se ho fatto i conti giusti con puntatori da 32bit) è una operazione da qualche microsecondo pure per un processore 486...
Dipende da come l'ambiente di sviluppo (se il programma viene lanciato da lì) o l'OS decide di gestire l'allocazione (gestione che tra l'altro è, e deve essere, totalmente trasparente al programma e all'utente).

demos88
22-10-2011, 18:27
ops doppio

Freaxxx
22-10-2011, 19:12
capisco, ma di fatto la gestione della memoria è affidata al kernel dell'OS.
L'hardware è a disposizione diretta del sistema operativo, tratta i dati per quel che sono e non si preoccupa di altro.
Quello che ti dice "gli indirizzi di memoria da 0x00000 a 0x000FF sono allocati" non è l'hardware, ma l'OS. Se l'OS invia un comando di dealloc, quell'area di memoria verrà in ogni caso liberata con una serie di istruzioni che la macchina esegue ad occhi chiusi e l'OS considera quell'area di memoria vuota e quindi non allocata, e anche se l'hardware non l'avesse liberata (penso che tra l'altro l'hardware non faccia niente) non importa, sarà marcata libera.
Le istruzioni di deallocazione sono corrette, probabilmente l'ambiente di sviluppo le tiene allocate perchè magari è in qualche particolare forma di debug.
Quello che voglio dire è che driver, hardware, bios ecc... possono certamente influenzare la velocità di allocazione e deallocazione, ma deallocare 22mB (se ho fatto i conti giusti con puntatori da 32bit) è una operazione da qualche microsecondo pure per un processore 486...
Dipende da come l'ambiente di sviluppo (se il programma viene lanciato da lì) o l'OS decide di gestire l'allocazione (gestione che tra l'altro è, e deve essere, totalmente trasparente al programma e all'utente).

perché, i driver che cosa sono se non moduli software per il kernel alla fine della fiera? specialmente quelli critici come quelli per il chipset; il tuo computer non fa altro che eseguire istruzioni, è una macchina stupida, ha di buono che è veloce e rispetta una sequenza operativa, ma da come scrivi sembra quasi che tu possa demandare tutto al kernel tanto da quel punto in poi sarà tutto chiaro, pulito e sicuro: ma anche no.

per quanto riguarda le varie modalità debug e i motivi per i quali non liberare subito una porzione di memoria non mi esprimo perché sono ovviamente tante le possibilità; magari prova anche tu con codeblocks.

tecno789
22-10-2011, 19:54
se si programma sotto windows questi problemi di memoria si verificano spesso.
sotto linux non ho mai visto questi problemi. Il codice mi sembra giusto, e quindi se lo testi su una macchina linux dovrebbe filare tutto liscio.

demos88
22-10-2011, 20:26
perché, i driver che cosa sono se non moduli software per il kernel alla fine della fiera? specialmente quelli critici come quelli per il chipset; il tuo computer non fa altro che eseguire istruzioni, è una macchina stupida, ha di buono che è veloce e rispetta una sequenza operativa, ma da come scrivi sembra quasi che tu possa demandare tutto al kernel tanto da quel punto in poi sarà tutto chiaro, pulito e sicuro: ma anche no.

per quanto riguarda le varie modalità debug e i motivi per i quali non liberare subito una porzione di memoria non mi esprimo perché sono ovviamente tante le possibilità; magari prova anche tu con codeblocks.
Io posso solo basarmi su quello che ho studiato nei vari corsi universitari e conoscenze personali, e francamente se la MMU hardware arrancasse sarebbe molto grave xD
Penso che sia un qualche passaggio nella gestione ad alto livello (software) della memoria, probabilmente una scelta implementativa, ma concordo che stiamo parlando del sesso degli angeli, ci sono troppe variabili da considerare :D

marco.r
23-10-2011, 14:19
perché, i driver che cosa sono se non moduli software per il kernel alla fine della fiera? specialmente quelli critici come quelli per il chipset; il tuo computer non fa altro che eseguire istruzioni, è una macchina stupida, ha di buono che è veloce e rispetta una sequenza operativa, ma da come scrivi sembra quasi che tu possa demandare tutto al kernel tanto da quel punto in poi sarà tutto chiaro, pulito e sicuro: ma anche no.

per quanto riguarda le varie modalità debug e i motivi per i quali non liberare subito una porzione di memoria non mi esprimo perché sono ovviamente tante le possibilità; magari prova anche tu con codeblocks.
L'hardware non ha il concetto di memoria libera od occupata, tantomento il driver del chipset. La memoria che vedi come occupata e' la memoria che il SO ha assegnato al processo. Tieni presente inoltre che tu non vai a prendere la memoria direttamente dal kernel, malloc/free non sono chiamate di sistema ma di libreria. Queste non si limitano ad allocare/liberare memoria, ma fanno diversi giri per cose come cercar di minimizzare la frammentazione, ad esempio cercando di riciclare memoria che e' stata liberata.
Se c'e' da cercare una causa per la memoria che non viene liberata, i primi indiziati sono proprio malloc/free (modalita' di debug, flag di compilazione etc.)
Detto questo su VS2010 e Windows 7 funziona regolarmente. Con che Compilatore/SO ti accade ?

nico88desmo
24-10-2011, 23:16
Ringrazio tutti per le diverse risposte.
Quindi il codice sorgente è corretto.

Non ho specificato, sto sviluppando un progetto in C sotto ambiente unix, più precisamente:
ubuntu 10.04
kernel 2.6.35-30-generic

L'hardware su cui sto provando è il seguente:
processore: core i5-460m
memoria: 4gb ram

Non ho ancora provato a fare la fflush, ora vedo se mi risolve questo problema.

Ad ogni modo, potrebbe essere che il processo libera la memoria, tuttavia se la "tiene" riservata per future allocazioni??

Ringrazio tutti ;)

marco.r
25-10-2011, 11:48
Ad ogni modo, potrebbe essere che il processo libera la memoria, tuttavia se la "tiene" riservata per future allocazioni??

Si', e' quello che dicevo precedentemente.
Il riuso della memoria allocata e poi liberata e' una delle tecniche utilizzate da una malloc per migliorare le performance.