6

Quali sono i modelli di memoria C++ 98 e C++ 11 per gli array locali e le interazioni con i thread?C++ variabili locali e thread (non thread_local)

Sono non riferendosi alla thread_local parola chiave C++ 11 , che appartiene a variabili globali e statiche.

Invece, mi piacerebbe scoprire qual è il comportamento garantito dei thread per gli array allocati in fase di compilazione. Per compile-time intendo "int array [100]", che è diverso per l'allocazione utilizzando la nuova parola chiave new []. Non intendo le variabili statiche.

Per esempio, diciamo che ho la seguente struct/classe:

struct xyz { int array[100]; }; 

e la seguente funzione:

void fn(int x) { 
    xyz dog; 
    for(int i=0; i<100; ++i) { dog.array[i] = x; } 
    // do something else with dog.array, eg. call another function with dog as parameter 
    } 

E 'sicuro di chiamare fn() da più thread? Sembra che il modello di memoria C++ sia: tutte le variabili e gli array non statici locali sono allocati nello stack e ogni thread ha il proprio stack. È vero (questo è ufficialmente parte dello standard)?

risposta

8

Tali variabili sono allocate nello stack e, poiché ogni thread ha il proprio stack, è perfettamente sicuro utilizzare gli array locali. Non sono diversi da, ad es. locale int s.

+0

Grazie. È scritto esplicitamente nello standard C++ 11? – mtall

+0

@mtall: indirettamente. Tutte le variabili non statiche in un corpo di funzione fanno parte dell'ambito della funzione e hanno durata di archiviazione automatica. Questo vale anche per le funzioni invocate da 'std :: thread :: thread (F &&, Args && ...)'. Quindi devi leggere quattro sezioni diverse se vuoi risolvere tutto insieme. – Zeta

+0

Alla fine, ogni chiamata a 'fn' creerà la propria istanza di' xyz'.Quindi se due thread chiamano 'fn' allo stesso tempo, allora entrambi i thread creeranno e modificheranno la propria istanza di' xyz', che è thread-safe. – TianyuZhu

2

C++ 98 non ha detto nulla sui thread. Programmi scritti altrimenti in C++ 98 ma che usano thread non hanno un significato definito da C++ 98. Naturalmente, è sensato per il threading delle estensioni fornire variabili locali private e stabili ai thread, e di solito lo fanno. Ma possono esistere thread per i quali non è questo il caso: per esempio i processi creati da vfork su alcuni sistemi Unix, in cui padre e figlio verranno eseguiti nello stesso stack frame, dal momento che lo v in vfork significa non clonare lo spazio degli indirizzi, e vfork non reindirizza il nuovo processo a una funzione diversa.

In C++ 11 è disponibile il supporto per la filettatura. Le variabili locali in catene di attivazione separate in thread C++ 11 separati non interferiscono. Ma se esci fuori dalla lingua e fai fuori il vfork o qualcosa che assomigli ad esso, allora tutte le scommesse sono disattivate, come prima.

Ma ecco qualcosa. Il C++ ora ha delle chiusure. Cosa succede se due thread invocano la stessa chiusura? Quindi hai due thread che condividono le stesse variabili locali. Una chiusura è come un oggetto e le sue variabili locali catturate sono come membri. Se due o più thread chiamano la stessa chiusura, allora hai un oggetto multi-thread di fatto i cui membri (cioè le variabili lessicali catturate) sono condivisi.

Un thread può anche semplicemente passare l'indirizzo delle sue variabili locali su un altro thread, causandone la condivisione.

+0

Distinguere tra acquisizione per riferimento e acquisizione per valore, poiché l'acquisizione per valore non condividerà nulla tra i thread. – Zeta

+0

'vfork()' blocca il processo genitore fino a quando il figlio non termina o carica un'altra immagine eseguibile su se stessa e se il bambino chiama qualsiasi altra funzione o ritorna da quella corrente, distruggerebbe lo stack genitore e comporterebbe un comportamento indefinito. Non riesco a vedere come si possa implementare un utile threading con 'vfork()'. –

+0

@HristoIliev Questo potrebbe essere vero per alcuni sistemi che stai guardando, ma non in Unix. Qui non vedo nulla sul blocco dei genitori: http://pubs.opengroup.org/onlinepubs/007908775/xsh/vfork.html – Kaz