2016-07-08 6 views
1

Ich lerne Multithreading in C++ mit Pthread auf Tutorials Point (es könnte alt sein, aber ich brauche nur etwas zu starten). Ich änderte den Code ein wenig:C++ Multithreading: Beenden nach dem Werfen einer Instanz von 'std :: length_error'

#include <pthread.h> 
#include <iostream> 
#include <string> 

#define NUM_THREADS 5 
#define DEBUG 
#undef DEBUG 

using namespace std; 

struct thread_data { 
    int thread_id = 0; 
    string message = ""; 
}; 

void *printHello(void *threadData) 
{ 
    struct thread_data* data = (struct thread_data*)threadData; 
    int thread_id = data->thread_id; 
    string message = data->message; 

    cout << "From thread " << thread_id << ": " << message << "\n"; 
    pthread_exit(NULL); 
} 

int main(int argc, char** argv) 
{ 
    pthread_t threads[NUM_THREADS]; 

    for (int i = 0; i < NUM_THREADS; i++) { 
     struct thread_data* data = new thread_data(); 
     string message = "Special message for thread #" + to_string(i) + "!"; 

     #ifdef DEBUG 
     cout << "DEBUG: " << "i = " << i << endl; 
     #endif 

     data->thread_id = i; 
     data->message = message; 

     cout << "main(): creating thread, " << i << endl; 
     int rc = 0; 
     rc = pthread_create(&threads[i], NULL, printHello, (void *) data); 

     delete data; 

     if (rc) { 
      cout << "Error: unable to create thread: " << rc << "\n"; 
      return -1; 
     } 
    } 

    pthread_exit(NULL);  
} 

ich mit kompiliert:

g++ -pthread -g -Wall -std=c++11 main.cpp -o main 

Und der Ausgang ist:

main(): creating thread, 0 
main(): creating thread, 1 
From thread 1: Special message for thread #1! 
main(): creating thread, 2 
From thread 2: Special message for thread #2! 
main(): creating thread, 3 
From thread 3: Special message for thread #3! 
main(): creating thread, 4 
From thread 4: Special message for thread #4! 
terminate called after throwing an instance of 'std::length_error' 
    what(): basic_string::_S_create 
Aborted (core dumped) 

Wenn ich nicht schaffen, die Fäden mit pthread_create und Call die printHello-Funktion direkt, kein Fehler auftritt. Manchmal warf das Programm stattdessen einen segfault und manchmal lief es glatt!

Ein anderes Problem ist, dass es eine Zeile geben sollte, die From thread 0: Special message for thread #0! von Anfang an sagt, aber dort war nicht.

Darüber hinaus manchmal die Nachricht "Special message for thread #n!" erschien überhaupt nicht.

Ich habe versucht, die Variablen der Struktur zu initialisieren, statisch zugewiesenen Speicher verwenden (anstelle von Heap-Stack von nicht new verwenden) in Zeile 31. Ich habe versucht, zu vermeiden Zeiger in der printHello Funktion zu nutzen, aber da das letzte Argument von pthread_create akzeptiert nur eine Zeiger auf die Argumente der Funktion konnte ich nicht tun.

Mein erster Verdacht war, dass etwas falsch ist, wenn ich data->message = message zuweisen, also habe ich versucht, die Zeichenfolge direkt zu data->message zuweisen, aber kein Glück. Aber ich denke immer noch, dass der Fehler da sein muss, da die Ausnahme std::length_error ist, ausgelöst durch 'basic_string'.

Oder, vielleicht, wenn ich data zu pthread_create passiere oder wenn ich die Besetzung in Zeile 18 mache, habe ich etwas falsch gemacht. Mein Gedanke ist, dass, wenn ich es an die Funktion übergebe, übergebe ich es als einen Zeiger, um es auf einen void Zeiger void * zu werfen. Wenn printHello den Parameter empfangen hat, wandle ich ihn auf den Typ thread_data* um, der ein Zeiger ist, was er ursprünglich ist.

Das ist, wenn ich so weit kommen kann. Bitte kommentieren Sie, wenn etwas in meinem Schreiben unklar ist (Englisch ist nicht meine Muttersprache).

Vielen Dank im Voraus.

Antwort

2

Sie löschen data direkt nach dem Erstellen des Threads. Das heißt, es gibt keine Garantie dafür, dass der Zeiger data immer noch auf ein Live-Objekt zeigt, wenn der Thread versucht, darauf zuzugreifen.

Sie sollten nur data löschen, wenn niemand mehr das Objekt verwendet. z.B. nachdem der Thread beendet ist (Sie können zB pthread_join verwenden, um das zu erreichen).

+0

Danke, das war das Problem. Ich bin dem Thread beigetreten, bevor ich delete und es hat gut funktioniert. –

+0

@QuanTran: Beachten Sie, dass Sie Ihre Threads nicht parallel ausführen, wenn Sie dem Thread innerhalb der for-Schleife beitreten. Sie möchten die Threads * nach * der for-Schleife verbinden (was auch bedeutet, dass Sie die Datenzeiger außerhalb der for-Schleife verfolgen müssen). –

+0

Danke, ich habe es bis jetzt nicht bemerkt.Ich habe tatsächlich Parallelen in Java gelernt, indem ich einen Download-Manager geschrieben habe, aber weil dieses Projekt größer ist als diese kleine Übung, habe ich die Threads erstellt und sie in verschiedenen for-Schleifen zusammengefügt, während ich für diese kleine Übung alles in eine für Schleife legte. Vielen Dank :) –

Verwandte Themen