"modo stupido di allocare" (commento non mio)

di il
11 risposte

"modo stupido di allocare" (commento non mio)

Dopo lo spavento col c++ ho fatto ritorno alle origini e ricomincio col c.

il mio proposito è provare ad allocare lo spazio per una stringa
senza sapere in anticipo quanto è lunga.

molto tempo fa avevo scritto questo:
#include <stdio.h>
#include <stdlib.h>

char*  allocastringa(char *s)	
{
	int i;
	char c;
	for(i=0;(c=getchar())!='\n'&&c!=EOF;i++)
	{
		s=(char *)realloc(s,(i+1)*sizeof(char));
		s[i]=c;
	}
	s[i]=0;
	return s;	
}

int main()
{

	char* s;
	s=allocastringa(s);
	printf("verifica: %s \n",s);

} 
e mi ricordo che mi avevano detto che era un modo stupido per farlo, però non mi ricordo perchè.
c'è qualcuno che sa dirmi perchè questo codice è ingenuo o se spreca qualcosa?

11 Risposte

  • Re: "modo stupido di allocare" (commento non mio)

    Non so chi ti abbia detto che è "stupido" (è esagerato), sicuramente non efficiente.

    Chiamare la realloc ad ogni carattere spreca solo tempo macchina e non serve a molto. Ti conviene allocare a blocchi (ad esempio da 4 K) e chiamare la realloc solo quando superi i 4 K in modo da averne altri 4. Poi, alla fine, chiami la realloc per avare la porzione corretta di memoria allocata. Così che chiami la funzione realloc 2 o 3 volte e non 5000 volte ...

    In ogni caso, c'è un errore perché non allochi lo spazio per l'ultimo byte, ovvero per

    s[ i ]=0;

    e poi devi inizializzare il puntatore

    char* s=NULL;
  • Re: "modo stupido di allocare" (commento non mio)

    Grazie della spiegazione e di avermi segnalato l'errore!
    Solo che non ho capito
    "alla fine, chiami la realloc per avare la porzione corretta di memoria allocata"...
  • Re: "modo stupido di allocare" (commento non mio)

    Cosa non hai capito (a parte il refuso)?
  • Re: "modo stupido di allocare" (commento non mio)

    Quando sarebbne "alla fine" e cosa significa "per avere la porzione corretta di memoria allocata"
  • Re: "modo stupido di allocare" (commento non mio)

    All'inizio allochi 4K di memoria e inserisci la tua stringa. Ovviamente se superi i 4K riallochi la memoria con 8K e continui ad inserire la stringa.

    Quando finisci di inserire la stringa (compreso il NULL finale) avrai magari scritto una stringa di 6K. Quindi, prima di uscire dalla funzione, riallochi la funzione per 6K riducendo la memoria allocata da 8 a 6K effettivamente usati. Hai chiamato la funzione realloc 3 volte e non 6000 (ovviamente 4K sono solo un esempio, puoi scegliere una quantità che vuoi).

    Ricorda anche che quando non ti serve più la memoria devi liberarla con

    free(s);
  • Re: "modo stupido di allocare" (commento non mio)

    Per l'altra questione dell'altro thread, se la funzione non restituisci il puntatore, allora il puntatore deve essere passato in modo da potere essere modificato, ovvero

    void allocastringa(char **s)

    e quindi nel main

    char* s = NULL;
    allocastringa(&s);

    e con le opportune variazioni all'interno della funzione dato che userai un doppio puntatore.

    Tutto riportato nel capitolo dei puntatori in un libro di C.
  • Re: "modo stupido di allocare" (commento non mio)

    Ho cancellato l'altro thread. La discussione e le variazioni al codice vanno contininuate qui.
    Non vanno creati altri thread.
  • Re: "modo stupido di allocare" (commento non mio)

    Ok, grazie delle risposte, quella dell'altro thread me la devo provare con calma, così vedo se ho capito
  • Re: "modo stupido di allocare" (commento non mio)

    Ok ma in generale hai capito per quale motivo ti "sconsigliavano" le realloc per ogni carattere?
  • Re: "modo stupido di allocare" (commento non mio)

    Sì ok, quello è chiaro, grazie.
    L'altro codice lo provo quando ho un po' più di svegliezza
  • Re: "modo stupido di allocare" (commento non mio)

    L'allocazione della memoria in C/C++ e' il VERO INCUBO di chi programma in questi linguaggi.
    E' la parte, in assoluto, piu' complicata.

    Tutto sembra molto semplice: c'e' la malloc e la free. La calloc e la realloc sono solo varianti 'intelligenti' della malloc.

    Il tuo caso e' molto semplice: devi allocare solo quello che basta per UNA stringa. Se allochi abbastanza spazio (MA NON TROPPO) te la cavi con un'unica allocazione.

    Le cose diventano assurdamente complicate se devi allocare tanti oggettini in relazione tra di loro.

    C'e' un intero mondo di 'strategie di allocazione della memoria'. Ti consiglio di approfindire spulciando un po' wikipedia

    Giusto per andare nel dettaglio dello sconsigliare la realloc. Ovviamente sconsigliarla non ha nessun senso MA I'idea di reallocare in continuazione ha degli effetti abbastanza devastanti (ovviamente su applicazioni decisamente piu' complesse, NON su un pezzetto di fodice di qualche decina di righe):

    1) l'allocazione NON E' istantanea, ci sono tutta una serie di strutture dati che I'll gestore della memoria del C deve gestire. Quindi, eallentamento del codice
    2) frammentazione della memoria: I'll C non ha un sistema di 'compattazione' della memotia allocata, QUINDI dopo un po (un BEL PO') la memoria totale disponibile si ritrova ad essere composta, alternativamente, da blocchetti allocati e blicchetti liberi. I'll risultato e' di avere ad esempio I'll 75% della memoria libera, ma I'll blocchetto piu' grande e' minuscolo. Conseguenza PUR avendo tanta memoria libera, NON E' POSSIBILE allocare una ragionevole quantita' di memoria.
Devi accedere o registrarti per scrivere nel forum
11 risposte