Newsgroup: it.comp.lang.c
Titolo: realloc

ciao a tutti,
ho fatto una semplice funzione (in linux) per la scansione delle 
directory con la gestione dinamica della mem, in locale tutto ok.
La stessa funzione mi crea dei seri problemi se la inserisco in un 
programmino server.
mi compare la seguente segnalazione, durante il while:
Time: Tue Feb  8 16:52:20 2005 Comando: dir host: 127.0.0.1 porta: 1133
*** glibc detected *** double free or corruption: 0x0804c048 ***
*** glibc detected *** double free or corruption: 0x0804c048 ***
*** glibc detected *** double free or corruption: 0x0804c048 ***
.........
/bin/sh: line 1:  6471 Segmentation fault      ./server
c'è una sola chiamata a free.
Sembra che ci siano dei problemi con la scrittura nella stringa 
dinamica, infatti lo stesso problema lo riscontro se sottodimensiono la 
realloc nel programmino in locale.
Se inizializzo la stringa (nel server) con malloc con valori grandi , 
esempio 10000, funziona.
Probabilmente mi sfugge qualcosa, non so...
ciao e geazie.
Porzione del main del server:
	...
	DirStream = opendir(buff);
	stringa = (char*)malloc(20);
	strcpy(stringa,"Risultato dir:\n\0");
	while(info = readdir(DirStream))
		scan( data, info, DirStream, stringa );
	...
Funzione:
void scan( struct stat data, const struct dirent *info, const DIR 
*DirStream, char *stringa )
{
int len, len2, size;
char temp[ MAX];
char temp2[ MAX];
	stat(info->d_name, &data);
	strcpy(temp, info->d_name);
	strcat(temp, "\t");
	gcvt(data.st_size, 10, temp2);
	strcat(temp, temp2);
	strcat(temp, " bytes\0");
	strcat(temp, "\t");
	if(S_ISDIR(data.st_mode))
		strcat(temp, "DIR\0");
	else if(S_ISREG(data.st_mode))
		strcat(temp, "File\0");
	strcat( temp, "\n");
	len = strlen(temp);
	stringa = (char*)realloc(stringa, sizeof(char) 
*strlen(stringa)+strlen(temp)+4);
	if (stringa == NULL)
	{
		printf("Allocamento memoria fallito\n");
		exit(1);
	}
	strcat(stringa,temp);
}

 }
Sarebbe meglio usare strncat e strncpy, in modo da essere sicuri al 100%
di non sforare i buffer.
Luca
-- 
Home: 
http://kronoz.cjb.net
The trouble with computers is that they do what you tell them, 
not what you want.
D. Cohen

 
Sì, ti sfugge un dettaglio relativo al funzionamento di 'realloc'.
Il puntatore che viene passato a 'realloc' viene invalidato. O meglio: dopo 
la chiamata a 'realloc' quel puntatore non va più considerato valido. 
L'unico puntatore valido a disposizione è quello restituito dalla funzione, 
il quale può benissimo avere valore diverso da quello iniziale.  La 
successiva 'free' andrà invocata su quel puntatore. 
Nel tuo esempio, il codice esterno alla funzione 'scan' non conosce il 
valore restituito da 'realloc'. La chiamata a 'free' viene eseguita su un 
puntatore che, a questo punto, potrebbe benissimo non essere più valido.
Max

 Luca
grazie,
fatto e funziona, l'unica variante: ho mantenuto il punt della stringa, 
senza ret, e quindi restuisco direttamente il punt. creato da realloc.
L'unica cosa che non mi spiego ancora, è che la funz. scan in locale 
andava benone, mentre nel programma client-server dava dei problemi.
Biofa.


grazie,
l'inesperienza porta a questi problemi.
ciao,
biofa.

 andava benone, mentre nel programma client-server dava dei problemi.
realloc potrebbe implementare un algoritmo furbo: se c'e` abbastanza
memoria dopo la zona da riallocare basta aggiornare la struttura dati
interna che tiene traccia della allocazioni per segnare quella memoria
come usata. In pratica l'area ottenuta con malloc viene ampliata, senza
alcun copia. Se, invece, non c'e` spazione per soddisfare la richiesta
e` necessario allocare un'area piu` grande da un'altra parte e copiare i
dati. In pseudo codice:
void *realloc(void *oldp, size_t newsize) {
        if (enough_space(oldp, newsize) {
                grow(oldp, newsize);
                return oldp;
        }
        newp = malloc(newsize);
        memcpy(newp, oldp, oldsize)
        free(oldp);
        return newp;
}
Il fatto che sia possibile o meno fare una realloc in place dipende da
tanti fattori esterni al programma, non controllabili direttamente da
te.
Luca
-- 
Home: 
http://kronoz.cjb.net
"La Via prosegue senza fine."
	Bilbo Baggins - Il Signore degli Anelli - J.R.R. Tolkien