2017-02-14 1 views
0

Ich versuche String-Vektorelement an die Funktion pthread_create() übergeben. Die Nachricht wird nicht in der Ausgabe gedruckt. Wo liege ich falsch?Wie übergibt man ein Vektorelement vom Typ string als Argument an pthread_create()?

#include <iostream> 
#include <pthread.h> 
#include <cstdlib> 
#include <vector> 

using namespace std; 

#define NUM_THREADS 5 

void *print_thread_details(void *thread_no){ 

    std::string str = *reinterpret_cast<std::string*>(thread_no); 
    cout<<"\n Running thread = "<<str<<endl; 
    pthread_exit(NULL); 

} 

int main(){ 

/*initialize an array of pthreads*/ 

    pthread_t threads[NUM_THREADS]; 
    int rc; 

    vector<string> v(NUM_THREADS); 
    for(int i=0;i<NUM_THREADS;i++){ 
     string s = "Thread No = "; 
     char temp = i+'0'; 
     s=s+temp; 
     v.push_back(s); 

     rc = pthread_create(&threads[i], NULL, print_thread_details,&v[i]); 

     if (rc){ 
     cout << "Error:unable to create thread," << rc << endl; 
     exit(-1); 
     } 
    } 

pthread_exit(NULL); 
return 0; 

} 

Output:

laufenden Faden =

Fadenlauf- =

Fadenlauf- =

Fadenlauf- =

Fadenlauf- =

+2

Wenn Sie Zugriff auf C++ 11 haben, empfehle ich Ihnen wirklich, 'std :: thread' eine Aufnahme zu machen. Es funktioniert tatsächlich mit dem Typsystem, das bedeutet nicht mehr "void". – NathanOliver

+1

Warum schreiben Sie C-Style-Code in C++? Warum verwenden Sie Makros für Konstanten? Warum benutzt du nicht 'std :: thread'? –

Antwort

1

Wie übergibt man ein Vektorelement vom Typ string als Argument an pthread_create()?

Genau wie Sie sie jetzt übergeben.

Sie müssen jedoch darauf achten, dass die Strings während des Threads nicht zerstört oder verschoben werden.

Die Nachricht wird nicht in der Ausgabe gedruckt.

Alle Zeichenfolgen, die Sie an die Threads übergeben, sind leer.


Ich vermute, dass Sie verwirrt sind, wie Vektoren arbeiten:

vector<string> v(NUM_THREADS); 

Dieser einen Vektor von 5 Elementen konstruiert. Jeder der 5 Strings ist leer.

v.push_back(s); 

Dies fügt ein sechstes ... 10.es Element in den Vektor. Diese Strings sind nicht leer, werden aber auch nicht an die Threads übergeben, da Sie die Indizes 0 ... 4 verwendet haben, die die leeren Strings enthalten.

Außerdem können diese Push-Backs dazu führen, dass der Vektor neu zugeordnet wird. In diesem Fall werden die an die zuvor erstellten Threads übergebenen Zeiger ungültig, was zu undefiniertem Verhalten führt.

Sie sollten wahrscheinlich ersetzen diese mit:

v[i] = s; 

Ein weiterer Ansatz ist mit einem leeren Vektor, und drücken Sie die erzeugten Zeichenfolgen in der Schleife zu starten. In diesem Fall müssen Sie jedoch den Speicher vorreservieren, um eine Zeigerinvalidierung aufgrund von Neuzuweisung zu vermeiden. Oder fülle den Vektor in einer separaten Schleife, bevor du irgendwelche Threads startest.


PS. print_thread_details gibt void* zurück, aber eine Rückgabeanweisung fehlt. Das Verhalten ist nicht definiert.

1

Das Problem ist, dass Sie den Vektorkonstruktor aufrufen, der den Vektor mit leeren Zeichenfolgen vorfüllt, und anschließend drücken Sie zusätzliche nicht leere Zeichenfolgen auf das Ende des Vektors. Der Vektor wird mit 10 Strings enden, nicht mit 5. Aber die Threads sehen nur die leeren Strings.

Entfernen Sie den Wert, den Sie an den Vektorkonstruktor übergeben, dann ist der Vektor anfangs leer. Rufen Sie die reserve() Methode des Vektors anstelle des Vektors vorzubelegen, ohne tatsächlich das Hinzufügen von Elementen zu ihm:

vector<string> v; 
v.reserve(NUM_THREADS); 

Andernfalls ohne reserve(), jeder Aufruf push_back() wird umverteilen möglicherweise den internen Bereich des Vektors, alle vorhandenen Zeichenfolge Zeiger ungültig zu machen, das würde Seien Sie schlecht, wenn Sie den Vektor bevölkern und die Threads gleichzeitig erstellen. Der sicherere Ansatz ist alle Saiten in den Vektor zu schieben, bevor dann die Fäden zu schaffen:

vector<string> v; 

for(int i=0;i<NUM_THREADS;i++){ 
    // consider using std::ostringstream instead... 
    string s = "Thread No = "; 
    char temp = i+'0'; 
    s=s+temp; 
    v.push_back(s); 
} 

for(int i=0;i<NUM_THREADS;i++){ 
    rc = pthread_create(&threads[i], NULL, print_thread_details,&v[i]); 
    ... 
} 

Auf einer Seite beachten, wenn Sie die Threads beginnen, müssen Sie warten, bis sie vor main() erlaubt zu beenden, um zu beenden Andernfalls kann der Vektor zerstört werden, während die Threads weiterhin die Zeichenfolgenwerte verwenden.

Verwandte Themen