Newsgroup: it.comp.lang.c++
Titolo: [XPOST] Comportamento anomalo

Ciao a tutti, e' la prima volta che scrivo qui. Sto scrivendo un
programmino in C ed ho un problema con una funzione.
=============================================
La funzione implementa il seguente algoritmo:
Le stringhe string1 e string2 sono riempite a sinistra ed a destra
da uno spazio.
Poi le stringhe si dividono nelle triplette di caratteri (trigrammi).
Quindi la somiglianza è calcolata come:
	s = 2*m/(a + b).
m è il numero di trigrammi in comune
a è il numero di trigrammi nella string1
b è il numero di trigrammi nella string2
Esempi: La somiglianza di ALEXANDRE e di ALEKSANDER è
	2*3 / (9+10) = 0.32(trigrammi in comune: _AL, ALE, AND).
=============================================
L'implementazione nel caso di n-grammi e parole di uguali lunghezze
e' questa:
float n_grammi(int enne, char *parola1, char *parola2, int length){
     char t1[enne][length];
     char t2[enne][length];
     char p1[MAX+2]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
     char p2[MAX+2]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
     int i,j,uguali=0,parz=0,num_ngrms;
     p1[0]='x';
     p2[0]='x';
     for (i=1;i<=length;i++){
         p1[i]=parola1[i-1];
         p2[i]=parola2[i-1];
     }
     p1[length+1]='x';
     p2[length+1]='x';
     num_ngrms=length-enne+3;
     for (i=0;i<=(num_ngrms-1);i++){
                for (j=0;j<=(enne-1);j++){
                 t1[i][j]=p1[i+j];
                 t2[i][j]=p2[i+j];
             }
     }
     for (i=0;i<=(num_ngrms-1);i++){
         for (j=0;j<=(enne-1);j++)
             if (t1[i][j]==t2[i][j]) parz++;
         if (parz==(enne)) uguali++;
         parz=0;
     }
     if (enne==1) return (float)((float)(uguali-2)/(float)length);
     return (float)((float)uguali/(float)num_ngrms);
}
La funzione funziona perfettamente pero' con parole di lunghezza >=8 si blocca
e mi chiude il programma.
Forse e' un problema di memoria... boh!
Qualche suggerimento?
Grazie.

Aggiungo che la funzione si blocca all'interno del primo ciclo for
dopo averlo eseguito 4/5 volte.

 Qualche suggerimento?
Usa un debugger.
Kiuhnm

 dopo averlo eseguito 4/5 volte.
Rettifica: il secondo ciclo for, questo:
for (i=0;i<=(num_ngrms-1);i++)
Scusate.

Risolto, avevo fatto un po' di pasticci con gli indici delle matrici.
Scusate nuovamente.
Se c'e' la gara per il post piu' inutile mi iscrivo :-)
Questo e' il codice corretto se vi interessa:
float n_grammi(int enne, char *parola1, char *parola2, int length){
     char t1[enne][length-enne+3];
     char t2[enne][length-enne+3];
     char p1[MAX+2]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
     char p2[MAX+2]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
     int i,j,uguali=0,parz=0,num_ngrms;
     p1[0]='x';
     p2[0]='x';
     for (i=1;i<=length;i++){
         p1[i]=parola1[i-1];
         p2[i]=parola2[i-1];
     }
     p1[length+1]='x';
     p2[length+1]='x';
     num_ngrms=length-enne+3;
     for (i=0;i<=(num_ngrms-1);i++){
             for (j=0;j<=(enne-1);j++){
                 t1[j][i]=p1[i+j];
                 t2[j][i]=p2[i+j];
             }
     }
     for (i=0;i<=(num_ngrms-1);i++){
         for (j=0;j<=(enne-1);j++)
             if (t1[j][i]==t2[j][i]) parz++;


     char p2[MAX+2]="\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
se hai il dubbio che si tratti di mancanza di memoria (visto che 
lo stack overflow è infido), non potresti provare ad allocare 
qualcosa di questa roba nello heap con new ? Ad esempio i primi 
due array sono dinamici e variabili, i secondi due array, che 
sono fissi, potresti dichiararli static (e quindi, anche se 
locali come scope, non graverebbero sullo stack). Sarò 
paranoico, ma ho il terrore degli oggetti sullo stack, in quanto 
non sai mai bene quanto ne rimane, e non c'è modo standard per 
capirlo in anticipo (tra l'altro sia questa lacuna sia quella di 
non poter conoscere lo heap libero, le ritengo gravissime pecche 
dei memory manager standard, e nn mi spiego perché non ci si sia 
messa una pezza standard da tempo).
ciao
Soviet
CUT ALL

 messa una pezza standard da tempo).
Perché vi sono due modi di approcciare il problema della mancanza di 
risorse: verificare la disponibilità prima di allocarle o provare ad 
allocarle e verificare se c'è stato un errore.
Se lo standard prevedesse delle funzioni per la prima strategia, il 
linguaggio non sarebbe portabile in quanto sulla maggior parte dei 
sistemi le funzioni per verificare le risorse a priori non sarebbero 
implementabili.
La seconda strategia è già disponibile nello standard per l'allocazione 
della memoria. Per il caso dello stack lo standard la permette ma non la 
impone (in quanto non è sempre implementabile).

 impone (in quanto non è sempre implementabile).
Prima o poi non dovremo più preoccuparci dello stack.
Comunque i processori IA prevedono stack dinamici quindi nel mio OS, per 
es., saranno tali.
Kiuhnm

 eseguire atexit o simili
Nel caso dello stack si.
Per questo un sistema critico si deve sempre basare su API specifiche. 
Il SW deve evitare a priori la ricorsione, conoscere a priori la 
dimensione massima dello stack che userà, essere compilato o lanciato in 
maniera da avere sufficiente stack.
E questo solo sui sistemi che ti permettono di farlo (non tutti i 
sistemi sono adatti a eseguire SW critici).

 es., saranno tali.
Dinamico o meno un limite lo ha. Lo avrà sempre.
Un sistema critico evita a priori la ricorsione e conosce a priori l'uso 
massimo dello stack che farà.

 massimo dello stack che farà.
Un sistema non critico no.
Kiuhnm

 windows.
Si. Ma alloc/free non alloca RAM. Alloca spazio di indirizzamento 
virtuale. Se per un errore il tuo programma ha un "leak" e lo esegui 
sotto linux impiegherai parecchio prima che il new lanci un'eccezione. 
Quello che succede è che man mano che le risorse richieste aumentano il 
programma comincerà a rallentare, ogni nuovo blocco di memoria richiesto 
al SO richiederà un tempo maggiore per essere allocato. Poi comincerà a 
rallentare anche il sistema.
Molto prima che il programma riceva un'eccezione qualcuno lo killerà.
Attento: non fare queste prove sulla tua installazione "desktop" linux 
che non è compilata per gestire questi problemi. Otterresti un 
rallentamento di tutta la macchina e finiresti con lo spegnerla come se 
fosse andata in hang. Ma non lo è: è solo terribilmente lenta. Su un 
sistema server ben configurato almeno la console di amministrazione 
accedibile via seriale rimarrebbe relativamente "responsiva". E 
probabilmente ci sarebbe comunque un qualche watchdog che killerebbe il 
tuo programma senza intervento esterno.
La filosofia di base è questa: se il programma può giungere a termine 
meglio che ci impieghi ore o giorni e dia un risultato piuttosto che non 
permettergli di arrivare in fondo.
Chi fa richieste ragionevoli viene servito ragionevolmente, gli altri 
verranno comunque serviti, se è possibile.
Hai mai visto quanto rallenta un programma (o un sistema) quando 
comincia il trashing? Ovvero quando la maggior parte degli accessi 
avvengono su disco?