|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Nov 2002
Messaggi: 4329
|
[c threads] variabili locali/globali...
ho un programma che crea piu thread...nel codice di uno di questi (per prova) ho scritto:
int x; x++; printf("%d\n", x); nel main creo una variabile p_thread e creo due volte, una di seguito all altra, il thread e la prima volta stampa 1, la seconda 2...wtf? ma la cosa piu bella: -creo un thread (con quelle 3 righe) -subito dopo un altro thread che non contempla neanche l esistenza di x -creo un altro thread dello stesso tipo del primo -stampo x e mi da un valore negativo immenso (penso min intero) buh, la morale e che a me serve avere delle variabili dichiarate all interno del codice di un thread e alle quali abbia accesso solo quel thread e non qualsiasi altra fregnaccia...si puo fare? come? grazie in anticipo
__________________
|18k+|slk800|a7n8x|1Gb/ddr400|Gf4mx440|Pio108|WD 160Gb|Case|Uni|Album|AnimeClick|OneManga| |ClassicThrash!|BNR Metal|TrueMetal|Dime|Chuck| |
![]() |
![]() |
![]() |
#2 | ||
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Mentre faccio un up espongo meglio il problema in quanto dnarod, a forza di vedere solo codice, si e' dimenticato l'italiano....
Il programma in questione e' un daemon che rimane in esecuzione in un sistema in attesa di richieste da parte di vari clients che concorrenzialmente lo andranno ad interpellare. Senza andare troppo nel dettaglio, inutile, ad ogni richiesta questo daemon lancia un programma figlio, nella fattispecie un nuovo thread, che si occupera' di questa richiesta in modo che il programma padre possa rimettersi nuovamente, ed immediatamente, in "ascolto" di nuove richieste. Il nocciolo del problema e' che per assicurare la concorrenzialita' tra i processi di questo sistema non possiamo far uso del classico pthread_join(che consiste nell'aspettare la terminazione del thread 'x') nel daemon. In questo modo la concorrenzialita' tra i processi viene mantenuta e con il corretto uso dei mutex viene anche mantenuta la mutua esclusione nelle sezioni critiche di ogni thread lanciato. Fin qua sembra che abbiamo capito tutto e che il programma possa funzionare senza problemi, PERO' durante l'esecuzione abbiamo notato che alcune variabili, dopo un paio di threads lanciati, risultavano "sporche" e qui si riconduce il post di dnarod: Quote:
Quote:
![]() ![]() ![]()
__________________
spammo un casino! ![]() |
||
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Si può vedere il codice ?
|
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Nov 2002
Messaggi: 4329
|
è enorme, si fa solo confusione...metto le parti significative...
------------------------- dal main: Codice:
[...] pthread_t T; [...] while(1) { pthread_create(&T, NULL, ilnostrothread, NULL); } [...] Codice:
void* ilnostrothread() { [...] int x; x++; printf("%d\n", x); [...] pthread_exit(NULL); } se viene fatta la stessa richiesta al server piu volte (si creano piu thread) la prima stampa 1, la seconda 2, ecc...le prove sono fatte a mano, quindi i thread muoiono sicuramente e non si incrociano mai...poi magari la cosa ha anche un suo senso logico, ma quel che interessa a me è altro, solo che non so come ottenerlo e non trovo informazioni da altre parti; spero di aver reso l idea, altrimenti mi sa pvt...
__________________
|18k+|slk800|a7n8x|1Gb/ddr400|Gf4mx440|Pio108|WD 160Gb|Case|Uni|Album|AnimeClick|OneManga| |ClassicThrash!|BNR Metal|TrueMetal|Dime|Chuck| Ultima modifica di dnarod : 06-11-2007 alle 16:33. |
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
x è locale a quell'istanza del thread...ogni thread ha la sua x che viene creata al momento della creazione del thread e distrutta al momento che la funzione del thread termina la sua esecuzione. In teoria gli altri thread potrebbero però accedere a x conoscendone l'indirizzo.
Quindi se x cambia il suo stato senza che venga acceduta dal thread che la crea è possibile che si tratti di un buffer overflow...in pratica gli altri thread cercando di operare su PROPRI dati vanno erroneamente a sovrascrivere il contenuto di x ![]() |
![]() |
![]() |
![]() |
#6 |
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Si, l'avevamo pensato anche noi però a questo punto come si può risolvere?
Cioè, che senso ha fare threads se poi le variabili PRIVATE di un thread vengono sovrascritte "per sbaglio" da un altro thread che sta scrivendo le sue private? Non è che questo "per sbaglio" è dovuto a come chiamiamo/usiamo i threads? Non esiste una dichiarazione privata(ahhh Java come ti amo) per queste variabili? Grazie in anticipo per l'attenzione e le risposte ![]()
__________________
spammo un casino! ![]() |
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Il modo per risolvere è trovare a cosa è dovuto il buffer overflow
![]() Non certo rendere più "privata" la variabile... Il valore in cui viene modificato è sempre lo stesso ? |
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Nov 2002
Messaggi: 4329
|
il fatto è che qui funziona cosi:
1)creo il thread 2)il trhead fa quello che deve fare e di sicuro muore (perche lo creiamo a mano con un menu maffo controllato da shell) 3)solo dopo creiamo il prossimo (con un buon secondo di ritardo almeno)... han tempo a morire 100 threads in quell arco di tempo (alla fine all interno del codice fara si e no una decina di operazioni, cioe nulla), cioe dovrebbe essere impossibile che un thread possa sporcare un altro, anche se è l unica idea che è venuta in mente anche a me...
__________________
|18k+|slk800|a7n8x|1Gb/ddr400|Gf4mx440|Pio108|WD 160Gb|Case|Uni|Album|AnimeClick|OneManga| |ClassicThrash!|BNR Metal|TrueMetal|Dime|Chuck| |
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Mi viene un dubbio...ma questa x la inizializzi ogni volta ? Come fai ad assegnare il valore iniziale a x ?
|
![]() |
![]() |
![]() |
#10 |
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Viene inizializaata ad ogni chiamata di quel thread. Non viene settato un valore iniziale, int x; lo inizializza a 0.
Questo la prima volta, poi dalla seconda in poi prende l'ultimo valore di x...
__________________
spammo un casino! ![]() |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
int x;
non inizializza assolutamente a zero, se lo fa è dipende dal compilatore... La variabile deve essere inizializzata a zero ![]() |
![]() |
![]() |
![]() |
#12 |
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Si, diciamo che mi sono spiegato male, lo so che viene inizializzata random nel range dell'int, però in questo caso abbiamo fatto una comunissima prova ed al primo passaggio i++ printa "1", quindi si, dipende dal compilatore ma questo poco ci interessa.
Se, ad esempio, la inizializzassimo OGNI volta a 0, esempio: Codice:
void* ilnostrothread() { [...] int x = 0; x++; printf("%d\n", x); [...] pthread_exit(NULL); } Questo si, andrebbe bene nel caso in cui lanciassimo solo un thread dello "stesso tipo"( pthread_create(&T, NULL, ilnostrothread, NULL); ) alla volta aspettando la sua terminazione con il pthread_join nel main oppure con un mutex che tenga lockato il thread in tutta la sua computazione. Così abbiamo già appurato che funziona, però viene a mancare tutta la parte concorrenziale del progetto. Finalmente sono riuscito a spiegare il problema? Scusami ma spiegarlo è più difficile di quel che sembra.. ![]()
__________________
spammo un casino! ![]() |
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Come ho già detto la variabile x è allocata per ogni istanza del thread, quindi non puoi "sperare" che alla successiva istanza mantenga il valore dato precedentemente.
Per far sì che lo mantenga dovresti passare l'indirizzo di x alla pthread_create... Ad esempio: Codice:
int x; //allocata solo una volta .... .... pthread_create(&T, NULL, ilnostrothread, &x); void* ilnostrothread(void *arg) { int *x = (int *)arg; (*x)++; printf(("%d\n", *x); } |
![]() |
![]() |
![]() |
#14 |
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Si, e ti ringrazio molto della risposta e del tempo che dietro ci stai perdendo, grazie davvero.
Però noi non "speriamo" che la variabile sia condivisa, noi vogliamo che le variabili presenti nei vari threads non siano assolutamente condivise, questo perchè ognuno è assestante. Abbiamo usato questo esempio della x, ma l'abbiamo usato solo per provare che questa "incredibile condivisione" esiste e ci sta mandato a quel paese tutta la logica del progetto...
__________________
spammo un casino! ![]() Ultima modifica di Gnappy : 06-11-2007 alle 17:52. |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Apr 2000
Città: Vicino a Montecatini(Pistoia) Moto:Kawasaki Ninja ZX-9R Scudetti: 29
Messaggi: 53971
|
Ricapitolando...
Il thread viene fatto girare (chiamiamolo thread1), dichiarate una variabile locale ad un thread. e la variabile ha valore, casualmente devo aggiungere, zero...incrementate questa variabile e la stampate. Stampa 1. A questo punto il thread termina e lo spazio occupato dalla variabile x viene liberato. Il thread viene fatto girare nuovamente (chiamiamolo thread2), dichiarate una variabile locale ad un thread. e la variabile ha valore pseudocasuale. Voi invece vorreste che avesse valore 1. E' giusto ? Se c'è qualcosa di errato nel ragionamento che faccio cerca di riprendere le mie parole e di modificarle ad hoc. Se è giusto allora avete sbagliato dal punto di vista logico in quanto l'istanza di x in thread1 non ha niente a che vedere con l'istanza di x in thread2. Sono variabili diverse con tempi di vita disgiunti. L'unico modo per avere 1 in x nella seconda istanza del thread è che abbiate la fortuna che x, quella nuova, vada ad occupare la stessa posizione di memoria della x vecchia e che nel frattempo nessuno abbia scritto in quella locazione di memoria. |
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Quote:
Volete contare quanti thread sono stati eseguiti? Se si deve essere comune a tutti i thread. Altrimenti per il codice che avere postato x potrà assumere sempre e solo il valore 1. Per quanto rigurarda l'inizializzazione, può essere che le successive istanze del thread vadano ad occupare le medesime celle di memoria del precedente, con la conseguenza che per caso la x riassume il valore che aveva in precedenza. Quando viene istanziato un thread che non viene allocato nello stesso punto dei precedenti succede esattamente quello che riportate. Quella variabile deve essere inizializzata da ogni istanza del thread, ciò significa che, siccome non la volete condividere tra thread, potrà valere sempre e solo 1 alla fine del thread. |
|
![]() |
![]() |
![]() |
#17 | ||
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Quote:
Quote:
![]() Guarda, oltretutto io e dnarod non credo che siamo 2 completi dementi della programmazione, non ci sono "bugs di storta" nel codice, tipo una globale int x dichiarata o porcate simili... Credo di aver spiegato bene il problema qui e, se sei ancora così gentile da voler continuare ad aiutarci in questo problema, ti invito a rileggerlo. TY
__________________
spammo un casino! ![]() |
||
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
I vostri problemi risiedono nel fatto che non inizializzate le variabili, probabilmente perchè siete abituati al Java che lo fa da sè, mentre il C non lo fa.
Come più volte ripetuto se non inizializzate le variabili il loro valore è random, e se per caso il vostro thread è allocato nelle stesse celle del precedente (cosa non certo rara, osservando in debug spesso si vedono le variabili riassumere il loro vecchio valore, magari anche della precedente istanza), allora per puro caso il valore assunto coincide con quello vecchio e quindi vedete come se la variabile fosse condivisa, in realtà è un vostro errore di programmazione decisamente elementare. |
![]() |
![]() |
![]() |
#19 | |||||||
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Quote:
Quote:
Quote:
Quote:
L'unico modo che ho di verificare che ogni thread che viene creato è diverso da un altro è controllare attraverso la pthread_self(che ritorna l'ID del thread). Abbiamo controllato e ogni thread è diverso da un altro. Quote:
In ogni caso ti faccio una serie di esempi con questo codice nel thread: Codice:
void* ilnostrothread() { [...] int x = 0; sleep(2); x++; printf("%d\n", x); [...] pthread_exit(NULL); } Quote:
Quote:
![]()
__________________
spammo un casino! ![]() |
|||||||
![]() |
![]() |
![]() |
#20 | |
Member
Iscritto dal: Feb 2001
Città: Nelle Langhe, dove non c'è tecnologia ma solo buon vino
Messaggi: 154
|
Quote:
Nel nostro programma ogni variabile è inizializzata LOCALMENTE. Quindi siamo nell'esempio "Esempio con 3 threads che arrivano in maniera concorrenziale(conteporeaneamente)" del mio reply appena postato. Come vedi qui la x che sia inizializzata o meno conta poco, qua va a quel paese l'intera concorrenzialità del programma. E il motivo è dell'inspiegabile situazione in cui queste maledette variabili decidono di meschiarsi tra i threads. Entrambi(io e dnarod) abbiamo ben chiaro cosa succede quando questo codice viene eseguito e quella simulazione è uno dei possibili casi(poi dipende dallo scheduler), ma non abbiamo la minima idea di come risolvere per il semplice fatto che IN TEORIA QUELLE VARIABILI NON SI DOVREBBERO CONDIVIDERE. Grazie ancora per il supporto.. ![]()
__________________
spammo un casino! ![]() |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 11:52.