Newsgroup: it.comp.lang.c
Titolo: x Skyscraper ( Anagrammi e aiuto x compilatori )

via Mailgate.ORG Server - 
http://www.mailgate.org

decenti : non sempre posso lanciare Linux.
Dipende da cio' che devi fare !
Una programmazione seria sotto Windows vorrebbe che tu usassi l'ambiente grafico
e quindi ti conviene adoperare un compilatore adeguato.
Per il DOS, secondo me, il DJGPP va molto bene.
Skyscraper (apprezzatelo adesso : eviterete la coda)
----------------------------------------------------
 
andrea_...@bigfoot.com
----------------------------------------------------


The Dark Player (
the_dar...@yahoo.com
) wrote:
[ snip ]
: Ok, fatto e funziona perfettamente...
: Grazie MILLE.
Prova con parole di 11-12 caratteri ;)
: Ma proprio non capisco il problema dei compilatori Borland.
: So che lavorare sia sotto Dos che sotto Windowz non è che sia serio o almeno
: lavorando in Unix e Unix-Like come Linux lavori in maniera standart ( se
: esiste uno standart ), ma pensavo che le differenze si notassero su
: programmi più complicati o su gestione di dati terrificanti.
: Mai più pensavo che in programma di poche righe si notassero le differenze o
: addirittura dei non-funzionamenti.
In questo caso, pero', e' un programma ricorsivo: questo significa che
utilizza pesantemente lo stack. Evidentemente, lo stack del Turbo C e'
'piccolo' (non so se tu possa aumentarne le dimensioni).
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

'piccolo' (non so se tu possa aumentarne le dimensioni).
Non si tratta di questo [vedi sopra]


Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
: >Prova con parole di 11-12 caratteri ;)
: A me funziona anche con parole di 11-12 caratteri.
A me no.
[ snip ]
: >In questo caso, pero', e' un programma ricorsivo: questo significa che
: >utilizza pesantemente lo stack.
: L'uso dello stack che fa questo programma e' abbastanza leggero.
Ah...E come fai a dirlo ?
: Per parole di tre lettere, poi, non dovrebbero esserci proprio problemi.
: > Evidentemente, lo stack del Turbo C e'
: >'piccolo' (non so se tu possa aumentarne le dimensioni).
: Non si tratta di questo [vedi sopra]
Sopra c'e' solo una tua affermazione piovuta dal cielo, non molto ;)
Ciao ciao


Sopra c'e' solo una tua affermazione piovuta dal cielo, non molto ;)
Sopra c'e' un'affermazione ben piantata coi piedi per terra ed e' abbastanza ;)


Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
: >: A me funziona anche con parole di 11-12 caratteri.
: >
: >A me no.
: Avrai sbagliato qualcosa... ;)
E' codice /tutto/ tuo ;)
Comunque ho risolto (vedi oltre).
[ snip ]
: >: L'uso dello stack che fa questo programma e' abbastanza leggero.
: >
: >Ah...E come fai a dirlo ?
: Il codice si analizza, prima di giudicare.
Per analizzarlo, bisogna prima capirlo.
[ snip ]
: Totale generale = 3072 + 262 + 7 + 6 = 3347 byte.
Hmmmm....ma hai presente il piccolo particolare che ad ogni iterazione
viene richiamata scrivi_anagrammi() ? E che ad ogni chiamata viene
utilizzato lo stack ?
Tenendo per buoni tuoi conti, direi che per ogni chiamata:
 12 byte	scrivi_anagrammi()
  7 byte	concat_char()
262 byte	estratto()
281 byte	per chiamata (trascuriamo per comodita' remove_last_char())
Ora se ipotizziamo una parola di 256 caratteri, otteniamo 281*256 = 71936
byte, pari a circa 70 Kb.
Vedi che fai presto ad avere problemi con il Turbo C: nel modello small,
per esempio, ci sono 64Kb per tutto ;)
Ammetto che 3 caratteri sono pochini, pero'. Guardando il tuo codice, ho
trovato un altro candidato a dare problemi, ossia l'orripilante:
char * estratto( char * t, int i )
{
   string temp;
   strcpy(temp, t);
   while (temp[i] = temp[i+1]) ++i;
   return ( temp );
}
Ma cosa abbiamo qui: stai restituendo un array /locale/...
complimenti, e' la prima volta che vedo qualcuno fare questo errore,
fino ad oggi lo avevo trovato solo su manuali e FAQ, sotto la voce 
"Cose da non fare MAI" 8)
Comunque, una volta modificato il codice per eliminare questo obbrobrio,
in effetti il tuo programma 'sembra' funzionare senza problemi anche con 
il mio compilatore.
[ snip ]
: >Sopra c'e' solo una tua affermazione piovuta dal cielo, non molto ;)
: Sopra c'e' un'affermazione ben piantata coi piedi per terra ed e' 
: abbastanza ;)
...piedi d'argilla, mi pare ! ;)
Ciao ciao,


 
Occhio:
char * estratto( char * t, int i )
{
   string temp;
-------^ Usare char *malloc(sizeof(string));
   strcpy(temp, t);
   while (temp[i] = temp[i+1]) ++i;
   return ( temp );
}
Ritorna un puntatore ad una stringa allocata sullo stack!!
Con parole corte non succede niente (ci sono strlen(string)-strnel(t) [1^
iterazione] di spazio). Con parole lunghe sballa: chiamando estratto() il
loop di copia potrebbe non fermarsi mai. Il comportamento puo' cambiare da
compilatore a compilatore.

}
Si, in effetti, questo e' sbagliato, va allocata memoria dinamicamente.


Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
[ snip ]
: Errato, le funzioni "estratto()",  "concat_char()" e "remove_last_char()" 
: non sono "permanenti", sono esterne alla ricorsione.
: Allocano spazio sullo stack e lo deallocano alla loro uscita.
Hai ragione per quanto riguarda concat_char(): non c'entra nulla ;)
Per estratto(), pero', ho i miei dubbi: tu allochi un array di 256 byte
sullo stack, ne restituisci l'indirizzo, e poi...?
Se, come dovrebbe essere, lo stack fosse deallocato subito, l'indirizzo 
che hai passato a scrivi_anagrammi() conterrebbe spazzatura, e te ne 
saresti dovuto accorgere!
Ma tu hai detto che va tutto bene, anche con parole lunghe. 
A me questo ha fatto pensare che, forse, visto che l'hai scritto cosi':
        scrivi_anagrammi( estratto( t, i ), a );
il tuo compilatore arrangi le cose in modo da deallocare lo stack 
impegnato da estratto() solo all'uscita da scrivi_anagrammi(), in 
caso contrario non mi spiego come possa funzionare correttamente.
Se, per quanto strano, fosse cosi', allora dovresti calcolare anche 
i 256 byte per chiamata quando misuri l'occupazione dello stack.
[ snip ]
: >char * estratto( char * t, int i )
: >{
: >   string temp;
: >
: >   strcpy(temp, t);
: >   while (temp[i] = temp[i+1]) ++i;
: >   return ( temp );
: >}
: Si, in effetti, questo e' sbagliato
Su questo siamo d'accordo. ;)


caso contrario non mi spiego come possa funzionare correttamente.
Non credo proprio che sia cosi'.
Deallocare le informazioni dallo stack non significa cancellarle dallo stack.
L'operazione equivalente di deallocazione di dati in memoria non implica
necessariamente un'eliminazione dei dati stessi.
Solitamente, quando si alloca memoria, la porzione allocata viene
"contrassegnata" dalla routine di allocazione in modo che alla prossima
allocazione venga saltata in ragione di quanto e' grande (in quanto occupata).
(vedi le routine di allocazione di memoria che sfruttano i Memory Control Block
del sistema MS-DOS)
Quando si dealloca il puntatore che punta a quella porzione di memoria, viene
semplicemente "contrassegnata" nuovamente come libera, ma il suo contenuto non
viene cancellato.
Questo discorso e' valido sopratutto per una struttura dati come lo stack, in
quanto gestire l'allocazione e' semplice (basta un solo puntatore, lo stack
pointer ).
Il comportamento delle routine di allocazione varia a seconda dei diversi
compilatori.
Il DJGPP azzera anche il valore puntato dalle variabili puntatori quando vengono
deallocate, mentre il Turbo C++ no.
Questo *non* avviene *comunque* per lo stack.
Ecco perche' il ritorno a "scrivi_anagrammi()" non e' preceduto da una
cancellazione di "temp".
Dal programma di esempio che ti ho scritto qui sotto (ispirato a quello del K&R)
puoi capire il meccanismo in base al quale, finquando non si va a sovrascrivere
lo stack nella zona di memoria "rilasciata", il contenuto di quest'ultima vi
rimane.
#define NULL           0  /* valore del puntatore che segnale l'errore */
#define SPAZIO_MAX  1000  /* ampiezza dello spazio disponibile */
static char stack [ SPAZIO_MAX ] ;  /* memoria per alloc() */
static char * sp = stack ;          /* successiva posizione libera */
char * my_alloc( int n ) /* ritorna un puntatore ad n caratteri */
{
       if (sp + n <= stack + SPAZIO_MAX)
       {
          sp += n ;
          return ( sp - n ) ;
       }
       else return NULL ;
}
void my_free( char *p ) /* libera la memoria puntata da p */
{
     if (p >= stack && p < stack + SPAZIO_MAX)
        sp = p ;
}
int main()
{
    char * a, * b ;
    a = my_alloc ( 10 ) ;
    strcpy(a, "andrea");
 
    printf("%s\n", a);
    b = a ;
    my_free( a ) ;
    printf("%s\n", b); 
 /* ^ nonostante il puntatore "a" sia stato deallocato i dati ci sono ancora */
    return 0 ;


 impegnato da estratto() solo all'uscita da scrivi_anagrammi(),
Non credo che un compilatore possa prendersi queste libertà. Tutte le
variabili automatiche definite in estratto() devono essere distrutte
prima della fine della funzione e tutta la memoria dinamica liberata con
free() dentro la funzione non è più disponibile dopo la fine della
stessa.
EMG

 viene cancellato.
Questo non ti autorizza, però, ad utilizzare per altri scopi i dati
'contrassegnati' come cancellati. Almeno non in linguaggi come il C.
Farlo porta alla scrittura di programmi dal comportamento indefinito.
EMG

Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
[ snip ]
: Non credo proprio che sia cosi'.
Non lo credo neanche io, se e' per questo. Sto solo tentando
di spiegare come mai il tuo programma a /te/ funzioni, quando
siamo /tutti/ d'accordo che contiene (almeno) un errore grave.
: Deallocare le informazioni dallo stack non significa cancellarle dallo 
: stack.
: L'operazione equivalente di deallocazione di dati in memoria non implica
: necessariamente un'eliminazione dei dati stessi.
Ovvio, ma con parole lunghe (sottolineo, lunghe), prima o poi
arrivi a modificare l'area dello stack occupata dalla stringa
(e 'marcata' come libera): e' per questo che io dopo un po' vedo 
'caratteri strani'.
Non mi spiego, pero', perche' a te questo non succeda...


Enrico Maria Giordano (
e.m.gi...@flashnet.it
) wrote:
: Andrea Foco wrote:
: > 
: >         scrivi_anagrammi( estratto( t, i ), a );
: > 
: > il tuo compilatore arrangi le cose in modo da deallocare lo stack
: > impegnato da estratto() solo all'uscita da scrivi_anagrammi(),
: Non credo che un compilatore possa prendersi queste libertà.
Non lo credo neanche io. D'altra parte come spieghi altrimenti che 
il programma di Skyscraper gli funzioni con parole lunghe ?
Io vedo solo due possibilita':
1) in realta' il programma non funziona neanche a lui, ma Skyscraper 
   non se ne e' accorto ;)
2) per qualche strana ragione l'area allocata sullo stack viene 
   protetta (bug ?)
[ snip ]
: Tutte le variabili automatiche definite in estratto() devono essere 
: distrutte prima della fine della funzione 
Per quel che ne so, viene solo modificato il puntatore allo
stack, per cui le variabili automatiche sono ancora li', ma 
/solo finche' non vengono sovrascritte/.


stessa.
Attenzione, bisogna intendersi sul termine "distrutte" e "liberata".
In uno stack la liberazione della memoria allocata per le variabili locali
avviene mediante un semplice spostamento del puntatore e non va ad intaccare i
valori scritti nello stack stesso.
Quindi, il termine "distruzione" va inteso, in questo caso, come impossibilita'
di accedere ai dati, ma i dati ci sono comunque.


   protetta (bug ?)
Non credo.
In realta' credo che si tratti di un meccanismo un po' perverso di strane
corrispondenze nello stack, legate al fatto che ogni volta che veniva chiamato
estratto() in realta' veniva subito usato 1 solo carattere.
Non sono sicuro se sia per questo, ma visto che, risolvendo la cosa con
l'allocazione dinamica, funziona, non mi resta che pensare che il Turbo C
gestisca in fase di run-time lo stack in modo diverso dal DJGPP.
Del resto sono differenti in tante altre cose.


Farlo porta alla scrittura di programmi dal comportamento indefinito.
Questo e' sicuro ! ci mancherebbe che fosse una cosa fatta apposta !
Nel mio programma e' stato un errore dovuto alla distrazione di aver pensato a
"temp", nel ritorno della funzione, come (char *) e non come array di caratteri.


Scusate se mi intrometto :-)
Ma il post originario non chiedeva una soluzione per anagrammi?
Un anagramma non equivale alle permutazioni della parola originaria, ma a un sottoinsieme
formato da parole che abbiano un senso.
Allora, va bene usare un generatore di permutazioni, ma ogni parola generata dovrebbe
essere passata al vaglio con un dizionario per verificarne la fattibilita'.
Oppure, volendo essere piu' permissivi, che almeno la parola generata sia grammaticalmente
corretta.
Ad esempio: se ci sono due lettere uguali consecutive, queste devono essere due
consonanti, ad eccezione di 'q', 'h',(..) e non possono trovarsi ne' all'inizio ne' al
termine della parola. Oppure possono essere vocali, ma solo la 'a' e la 'e' (e in genere
dovrebbero trovarsi solo al termine della parola). Ecc.ecc.
Tempo fa', se non ricordo male, mi ero divertito ad impostare delle regole, ma non so dove
possano essere finite :-)
Comunque, posto del codice per la permutazione che, a mio avviso, e' molto semplice e
compatto. Volendo effettuare il controllo della parola ottenuta e' sufficiente modificare
la funzione out().
Usando la #define NOT_DUPLICATE e' possibile evitare duplicazioni dell'output quando la
stringa contenga caratteri uguali, es. "pippo" (ottimizzazione per il caso di controllo
effettivo per anagramma, evitando cosi' di verificare se la parola sia gia' uscita)
Occhio che il numero di permutazioni e' il fattoriale della dimensione dell'input.
Ciao
Nazzareno
------------------------------------------------------------------------------------------
** La stringa [s] poteva anche essere dichiarata globale ed evitare di inserirla nella
ricorsione, ma, secondo le buone regole della programmazione, e' meglio evitare variabili
globali
/* permutazioni */
#include <stdio.h>
#include <string.h>
#define NOT_DUPLICATE
static void perm(char *s,char *s1,int l);
#ifdef NOT_DUPLICATE
    static int myswap(char *s,int i);
#else
    static void myswap(char *s,int i);
#endif
static void out(char *s);
/* per allineamento sullo schermo */
static char SPAZI[82];
int main(void)
{
    char s[256];
    int l;
    int i;
    printf("Immettere la stringa da permutare -> ");
    scanf("%s", s);
    l = strlen(s);
    SPAZI[0] = ' ';
    for(i=1; 80 % (l+i); ++i)
        SPAZI[i] = ' ';
    perm(s, s, l);
    printf("\n");
    return 0;
}
void perm(char *s, char *s1, int l)
{
    int i;
    if(l > 1) {
       perm(s, s1 + 1, l - 1);
       for(i = 1; i < l; ++i) {
#ifdef NOT_DUPLICATE
            if(!myswap(s1, i))
                continue;
#else
            myswap(s1, i);
#endif
            perm(s, s1 + 1 , l - 1);
            out(s);
            myswap(s1, i);
            }
       }
}
void out(char *s)
{
    printf("%s%s", s, SPAZI);
}
#ifdef NOT_DUPLICATE
int myswap(char *s, int i)
{
    char c = s[0];
    if(c == s[i])
        return 0;
    s[0] = s[i];
    s[i] = c;
    return 1;
}
#else
void myswap(char *s, int i)
{
    char c = s[0];
    s[0] = s[i];
    s[i] = c;
}
#endif

Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
: >Non lo credo neanche io. D'altra parte come spieghi altrimenti che 
: >il programma di Skyscraper gli funzioni con parole lunghe ?
: Secondo me non e' un problema di lunghezza delle parole, ma un problema di
: gestione dello stack da parte del compilatore.
Vediamo di capirci: se usi il programma scorretto con una parola
di 255 caratteri, ti funziona ?
: >Io vedo solo due possibilita':
: >1) in realta' il programma non funziona neanche a lui, ma Skyscraper 
: >   non se ne e' accorto ;)
: Non e' vero, a me funziona realmente con parole lunghe.
Anche di 255 caratteri ? Credo sia questo il punto.
: E' mia premura, quale autore del programma, quello di controllare se il
: programma funzioni bene prima di darlo a qualcuno.
: In questo caso il problema della funzione "estratto()" e' stata una svista.
ROTFL
Chiamala svista 8)
: Perche' non dovrei correggerlo se fosse sbagliato ?
Mai detto niente in contrario. Personalmente sono incuriosito dal
fatto che un programma con un errore simile possa funzionare senza
dare problemi...
: >2) per qualche strana ragione l'area allocata sullo stack viene 
: >   protetta (bug ?)
: Non credo.
: In realta' credo che si tratti di un meccanismo un po' perverso di strane
: corrispondenze nello stack, legate al fatto che ogni volta che veniva 
: chiamato estratto() in realta' veniva subito usato 1 solo carattere.
Mah...stai ipotizzando anche uno stack gestito in maniera...strana ;)
: Non sono sicuro se sia per questo, ma visto che, risolvendo la cosa con
: l'allocazione dinamica, funziona, non mi resta che pensare che il Turbo C
: gestisca in fase di run-time lo stack in modo diverso dal DJGPP.
Io uso il gcc 2.7.2.3 sotto Linux, e come gia' detto, mi da' problemi
con parole sui 10-11 caratteri...
Giusto per curiosita' ho ricompilato con l'egcs 1.0.3, con lo stesso
identico risultato (spazzatura con parole lunghe 10 caratteri).
Inoltre non e' necessario (anche se forse e' la soluzione migliore)
usare l'allocazione dinamica: si puo' anche usare quella statica, a
patto di farlo correttamente.


Skyscraper (
s...@scraper.com
) wrote:
[ snip ]
: Nel mio programma e' stato un errore dovuto alla distrazione di aver 
: pensato a "temp", nel ritorno della funzione, come (char *) e non come 
: array di caratteri.
Cioe', avevi pensato di ritornare /solo/ un (char *) dove era
richiesto un array ? ;)
Scusa, credo che tu non abbia ancora capito bene il tuo /errore/ 
(non svista, chiamiamo le cose con il loro nome): il fatto e' che 
tu hai ritornato l'indirizzo di una variabile locale, ossia una 
variabile che all'esterno della funzione in cui e' definita /non 
esiste/ (piu' esattamente, non dovrebbe esistere: per il meccanismo 
che hai descritto anche tu, pure con esempietto scopiazzato dal KR, 
le variabili locali sullo stack non vengono azzerate, ma restano li' 
dove sono finche' non vengono sovrascritte).


Ahehm!! chiedo venia per il post precedente :-)
Piu' che #define NOT_DUPLICATE avrei dovuto scrivere #define REDUCE_DUPLICATE.
Era stata (a suo tempo) un'idea dell'ultima ora rimasta morta li.
In effetti non elimina completamente i duplicati - non puo' memorizzare tutta la storia
precedente - ma evita le duplicazioni nei casi certi.
Ciao
Nazzareno

dove sono finche' non vengono sovrascritte).
E allora ? questo lo sappiamo tutti.
Carissimo Foco, vediamo di dare un taglio a questa storia, visto che stai
andando avanti, piu' che per critica costruttiva, per spirito di contraddizione.


patto di farlo correttamente.
Questo e' un altro discorso e torno a ribadire che non sai leggere quello che
c'e' scritto.
Non ho detto che funziona SOLO con l'allocazione dinamica.
E comunque, non credo che il mio programma meriti tanta attenzione da parte tua
nello scervellarti per capire perche' funzioni o non funzioni...
Esci, trovati un hobby, fa' qualche altra cosa... ;)


formato da parole che abbiano un senso.
Per "anagrammi" l'autore del messaggio intendeva le permutazioni della parola
originaria.
Basta avere un dizionario indicizzato ed il programma e' facilmente modificabile
per fare cio' che dici.


 di accedere ai dati, ma i dati ci sono comunque.
E su questo non ci piove, almeno fino a quando il sistema non decide di
sovrascriverli, cosa che non č sotto il controllo del programmatore.
Comunque resta il fatto che i dati dei quali viene fatto il POP dallo
stack, per il programmatore č come se non ci fossero piů.
EMG

 "return (temp)".
Forse intendevi dire: se fosse stato un "char"? Altrimenti non ho
capito: il problema della restituzione di una variabile locale esiste
solo se questa è restituita per riferimento come per un char *. Mentre
un char semplice sarebbe stato restituito correttamente per valore.
EMG

Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
: >Cioe', avevi pensato di ritornare /solo/ un (char *) dove era
: >richiesto un array ? ;)
: Non era richiesto un array ma un "char *" dato che scrivi_anagrammi() e'
: definita come "scrivi_anagrammi( char *, ... ) ;".
ROTFL
Perche', sarebbe stato diverso se fosse definita come
scrivi_anagrammi( char a[], ...) ?
Non hai ancora imparato come funzionano gli array 8-D
Quello che intendevo io e' che scrivi_anagrammi() si aspetta
un array di caratteri su cui operare, e sembra che tu gli
voglia passare solo un (char *) (intendo solo un puntatore
a char /non/ inizializzato).
: >Scusa, credo che tu non abbia ancora capito bene il tuo /errore/ 
: >(non svista, chiamiamo le cose con il loro nome):
: Io il mio errore l'ho capito benissimo, ed e' un errore causato 
: da una svista.
Si si va bene...8)
: Esercitati a cercare di capire il senso delle parole ed il modo 
: in cui gli effetti seguono le cause.
Benissimo, vedo che te lo hanno gia' ripetuto molte volte, visto che 
lo hai imparato a memoria. Ora pero', cerca anche di applicarlo. ;)
: >il fatto e' che 
: >tu hai ritornato l'indirizzo di una variabile locale, ossia una 
: >variabile che all'esterno della funzione in cui e' definita /non 
: >esiste/ 
: Perche' purtroppo il C non l'ho inventato io 
ROTFLASTC
(...mitica 8)
: e se "temp" fosse stato un "char*" la cosa avrebbe funzionato, ma 
: il comando "return" rimaneva sempre e comunque "return (temp)".
8)
Guarda lascio perdere. E' evidente che parli a vanvera...
[ snip ]
: Carissimo Foco, vediamo di dare un taglio a questa storia, visto che 
: stai andando avanti, piu' che per critica costruttiva, per spirito di 
: contraddizione.
Andavo avanti solo perche' /l'unica/ cosa interessante del tuo
programmino era che, secondo te, funzionava.
Ora, io penso che non sia possibile. D'altra parte, penso pure 
che continuerai a dire che a te funzionava perfettamente.
Sono d'accordo che non vale la pena continuare...


Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
: >Vediamo di capirci: se usi il programma scorretto con una parola
: >di 255 caratteri, ti funziona ?
: Te lo ripeto per l'ultima volta : anche se e' strano, si' funziona.
E non ti stupisce la cosa ? Ti rendi conto che significa che
l'area allocata (scorrettamente) da estratto() sullo stack 
e' interamente protetta ? Non viene mai sovrascritta, anche
se e' (o dovrebbe essere) 'marcata' come libera ?
: Ma questo non vuol dire che sia corretto, anzi.
Be' su questo ormai siamo tutti d'accordo.
[ snip ]
: >Chiamala svista 8)
: Difatti e' una svista, che tu ci creda o no ...
Guarda lascio perdere per pura pieta' di chi legge...8)
: Io ho scritto programmi *funzionanti* molto piu' complessi di questo 
Dubito assai...ma forse abbiamo concetti diversi di complesso ;)
In quanto al funzionante, ti ricordo che il programmino che
hai postato, a tuo dire, e' perfettamente funzionante, anche
se contiene un /grave/ errore...ops una /grave/ svista ;)
[ snip ]
: >Mai detto niente in contrario. Personalmente sono incuriosito dal
: >fatto che un programma con un errore simile possa funzionare senza
: >dare problemi...
: Perche' probabilmente ti ostini a non capire quale potrebbe essere 
: il problema.
O.K. genio, sono tutto orecchi: dammi una spiegazione valida.
Ah...parlare di 'strane corrispondenze nello stack' non e' una
spiegazione valida ;)
[ snip ]
: E comunque, non credo che il mio programma meriti tanta attenzione 
: da parte tua nello scervellarti per capire perche' funzioni o non 
: funzioni...
Vedi questa e' un'altra cosa che mi lascia un po' perplesso: il tuo
programmino e', in effetti, un esercizietto da nulla, pure scritto 
male e buggato 8)...la /sola/ cosa davvero interessante e' che 
funzioni (a tuo dire, s'intende)...non riesco a convincermi che
questo fatto, il solo davvero degno di attenzione, non ti incuriosisca
neanche un po'... 8-?


che continuerai a dire che a te funzionava perfettamente.
Perche' cosi' e'.
Questo non significa che io affermi che sia corretto.
Se vuoi ti posto l'output di una parola di 256 caratteri cosi' ti convinci.
E ribadisco : nonostante il programma sia sbagliato.


neanche un po'... 8-?
Certo che mi incuriosisce, ma la curiosita' e' venuta sempre meno, da quando ho
corretto il codice.
Sai com'e', per noi "normali" indagare sul perche' una cosa funzioni e' molto
meno attraente che farlo per una cosa che *non* funzioni... :)
E poi, anche il perche' Windows95 si inchiodi ogni 2 secondi mi incuriosisce, ma
di sicuro non mi vado a studiare il kernel del sistema operativo istruzione per
istruzione.
E' per questo che quando mi chiama Bill faccio dire che non ci sono :)
Comunque, traendo le somme, e' evidente che questa conversazione sta degenerando
in qualcosa che prescinde dal linguaggio C e, immagino stia diventando *molto*
pesante per chi legge, per cui ti faccio presente che ho intenzione, per non
continuare a leggere (e a far leggere) le tue stupidita', di porre un simpatico
timbro IGNORE THREAD su questa serie di messaggi.
Rispondi pure, ma rendo noto che non replichero' perche' non ti leggero'.
E per dirla alla "Foco" ciao...ciaoooo... !!! ROTFL 8)
p.s.: la funzione IGNORE_THREAD() non e' portabile...


Skyscraper (
s...@scraper.com
) wrote:
: Un bel giorno, tutt'a un tratto Andrea Foco si mise a scrivere :
: E' evidente che hai una strana idea di come venga allocata la memoria per
: pensare che sia "protetta" ! (che abbia pure un angelo custode ?).
Ho usato 'protetta' nel senso di 'mai sovrascritta', come e' ovvio
dal contesto.
: Sto cercando di farti capire (inutilmente, ovviamente, perche' comincio a
: dubitare che tu abbia una minima capacita' di comprensione :) che,
: *probabilmente* (non ne sono sicuro perche' non l'ho testato) il valore
: contenuto nello stack, non influisce, sebbene venga sovrascritto 
: (in parte ?), sul corretto funzionamento del programma, perche' di esso 
: ne viene elaborato un solo carattere alla volta, che, guarda caso, in 
: quel momento, si trova in una zona che non e' stata *ancora* sovrascritta.
Il fatto e' che tu 'scorri' la stringa t in scrivi_anagrammi()! Pensa alla
prima iterazione: tu copi sullo stack la stringa (chiamiamola Y), passi 
alla nuova chiamata di scrivi_anagrammi() l'indirizzo (che nel frattempo 
e' stato marcato 'libero') e cosi' via scendendo lungo lo stack, O.K. ?
Pero', ad un certo punto, dovrai risalire lo stack per andare a modificare
la prima lettera della stringa originaria (ritorni, cioe', al primo for), 
e a questo punto leggerai il secondo elemento della stringa Y, se c'e' 
ancora, O.K. ?
Ora considera quando arrivi a leggere /l'ultimo/ carattere della stringa
di 256 elementi allocata per prima nel modo scorretto: significa che questa 
'benedetta' stringa e' rimasta intoccata fino ad allora...
(c'e' un particolare, pero': vedi piu' avanti)
[ snip ]
: Questo *probabilmente* risulta, come gia' ampiamente da me detto, ma da te,
: evidentemente, non recepito, da una *probabile* differenza nella gestione 
: dello stack da parte dei nostri due compilatori.
Il fatto e' che io ho provato sia con il gcc 2.7.2.3 sia con l'egcs 1.0.3,
mentre da quel che ho capito tu usi il DJGPP, ossia il gcc 2.8.1. Ora sono
tutti compilatori della stessa 'famiglia', non credo che ci siano differenze 
cosi' marcate nella gestione dello stack.
[ snip ]
: Ho forse detto che la zona non viene sovrascritta (anche se in parte) ?
Allora come spieghi che una stringa di 255 elementi non venga neanche
sfiorata ? 
Mi pare di capire (correggimi se ho interpretato male) che tu ipotizzi 
che, man mano che scorro la prima stringa salvata sulla zona libera 
dello stack, la stringa stessa venga sovrascritta, ma in modo tale da 
modificare /solo/ le lettere gia' utilizzate...
[ snip di un certo numero di sciocchezze ;) ]
: >
: >O.K. genio, sono tutto orecchi: dammi una spiegazione valida.
: Grazie per il "genio", sapevo che prima o poi l'avresti riconosciuto ! :)
Spero non ti sconvolga sapere che era ironico ;)
[ snip ]
: La spiegazione valida non la conosco neanch'io, e forse non la voglio 
: neanche conoscere, 
Vedi, questa e' la cosa peggiore. Non capita spesso di trovare l'occasione
di analizzare a fondo problemi del genere (avendo il tempo di farlo, si
intende ;)
: figurati se perdo tempo per dartene una, visto che proprio adesso
: devo decidere se sia meglio uscire con la propria ragazza o studiarsi 
: lo stack del programma...
Guarda, considerati i tuoi scarsi risultati 8-P, mi permetto di 
consigliarti la ragazza...
: Tu al posto mio che faresti ?, io, al posto tuo, uscirei con la tua 
: ragazza ;)
Touche' 8)
[ snip ]
: >Vedi questa e' un'altra cosa che mi lascia un po' perplesso: il tuo
: >programmino e', in effetti, un esercizietto da nulla, pure scritto 
: >male e buggato 8)...
[ snip ]
: Bravissimo ! sei in gamba a pestare sotto i piedi il lavoro degli altri, ma
: bisogna vedere se questo esercizietto da nulla, come lo chiami tu, seppure
: sbagliato nell'aspetto pratico, ma rispondente ad una teoria impeccabile, 
: era alla tua portata.
Non ti offendere, ma davvero consideri quel programmino di circa 
70 righe piu' di un esercizietto ? 
Nota: lo considererei tale anche se lo avessi scritto io, o chiunque
altro. 
In quanto al resto, forse sono stato un po'...ahem brusco ;), ma sono
dati di fatto.
[ snip ]
: Ti posso fare io una domanda, a questo punto ?
[ snip ]
: Non credi che e' un po' strano ?
<PARENTESI>
Non prenderla come un'offesa, ma si scrive:
non credi che /sia/ un po' strano ?
Ti prego di scusarmi e di non considerarlo un modo di prenderti
in giro o altro: e' solo che certi errori mi innervosiscono un po'.
</PARENTESI>
Per il resto, restando nel campo delle supposizioni, potrei ipotizzare 
che tu non abbia usato parole lunghe per testarlo, e ti sia accorto 
dell'errore solo dopo 8-P
[ snip ]
: >non riesco a convincermi che
: >questo fatto, il solo davvero degno di attenzione, non ti incuriosisca
: >neanche un po'... 8-?
: Certo che mi incuriosisce, ma la curiosita' e' venuta sempre meno, da 
: quando ho corretto il codice.
Te lo ripeto: il tuo codice e' solo un esercizietto e nulla piu'. L'errore, 
o se preferisci le 'strane corrispondenze', che hai trovato sono /molto/ 
piu' interessanti.
: Sai com'e', per noi "normali" indagare sul perche' una cosa funzioni e' 
: molto meno attraente che farlo per una cosa che *non* funzioni... :)
Questa e' una sciocchezza: se io adesso mi mettessi a volare e venissi a 
sputacchiarti sulla testa ;), penso che molti sarebbero interessati a
capire come faccio (a volare, ovviamente ;).
: E poi, anche il perche' Windows95 si inchiodi ogni 2 secondi mi 
: incuriosisce, ma di sicuro non mi vado a studiare il kernel del 
: sistema operativo istruzione per istruzione.
Anche perche', probabilmente, non ci caveresti un ragno dal buco 8)
[ snip ]
: Comunque, traendo le somme, e' evidente che questa conversazione sta 
: degenerando in qualcosa che prescinde dal linguaggio C e, immagino stia 
: diventando *molto* pesante per chi legge, 
/Mi pare/ che discutere su come i compilatori C usano lo stack
sia In Topic.
Chi legge puo' fare a meno di farlo ;). 
Se la cosa ti ha stufato puoi semplicemente smettere di rispondere, non
serve che ti nascondi dietro a fantomatici 'altri'.
: per cui ti faccio presente che ho intenzione, per non
: continuare a leggere (e a far leggere) le tue stupidita'
Mah...se non hai argomenti migliori, ritirati pure.
: Rispondi pure, ma rendo noto che non replichero' perche' non ti 
: leggero'.
Peccato...per te 8-P


 70 righe piu' di un esercizietto ?
Attenzione a prendere sotto gamba gli 'esercizietti'. Specie in un
linguaggio come il C, anche una sola riga può nascondere implicazioni a
cui uno non aveva pensato e dare errori dei tipi più svariati. E
comunque un programma più grande, se ben fatto, non è altro che un
insieme di 'esercizietti'...
EMG