2016-07-08 12 views
1

私はマルチスレッドをC++で学んでいるのですが、Tutorials Pointのpthreadを使用しています(古いかもしれませんが、私は、コードを少し変更:C++マルチスレッド: '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);  
} 

私がしてコンパイル:

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

、出力は次のとおりです。

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) 

私はpthread_createを使用してスレッドと呼び出しを作成しない場合printHello関数を直接呼び出すと、エラーは発生しません。場合によっては、プログラムが代わりにセグメンテーションをスローし、時にはスムーズに実行されました。

もう1つの問題は、最初からFrom thread 0: Special message for thread #0!という行があるはずですが、そうではありませんでした。

さらに、「スレッド#nのための特別なメッセージ!」というメッセージが表示されることがあります。全く現れなかった。

私は構造体の変数を初期化しようとしましたが、行31で静的に割り当てられたメモリ(ヒープの代わりにスタック)を使用しました。printHello関数でポインタを使用しないようにしましたが、pthread_createの最後の引数は関数の引数へのポインタ、私はそれを行うことができませんでした。

私が最初に疑ったのは、data->message = messageを割り当てたときに何か問題があったため、直接文字列をdata->messageに割り当てようとしましたが、運はありませんでした。しかし、私はまだ例外がstd::length_errorであり、 'basic_string`によってスローされているので、エラーがそこになければならないと思います。

または、datapthread_createに渡すか、18行目にキャストするときに間違ったことがありました。私はそれを関数に渡すとポインタとして渡し、それをvoidポインタvoid *にキャストすると考えています。 printHelloがパラメータを受け取ったとき、それはポインタであるthread_data*にキャストします。これは元のものです。

これまで私がこれまで思いついたのは、私の文章にはなんらかの不明点がある場合はコメントしてください(英語は母国語ではありません)。

ありがとうございます。

答えて

2

スレッドを作成した直後にdataを削除しています。つまり、dataポインターは、スレッドがライブオブジェクトにアクセスしようとするまでにまだそのオブジェクトを指しているという保証はありません。

もう誰もオブジェクトを使用しない場合は、dataだけを削除してください。例えば。スレッドが終了した後(例えば、pthread_joinを使用してそれを達成することができます)。

+0

ありがとう、それは問題でした。削除を呼び出す前にスレッドに参加し、うまくいきました。 –

+0

@QuanTran:forループ内のスレッドに参加すると、スレッドを並行して実行していないことに注意してください。 * for *ループの後の*スレッドに参加することもできます(これは、forループの外側のデータポインタを追跡する必要があることを意味します)。 –

+0

ありがとう、私は今まで気付かなかった。私は実際にダウンロードマネージャを書くことでJavaの同時実行性を学んだが、そのプロジェクトがこの小さなエクササイズよりも大きいので、スレッドを作成してforループに参加させたが、この小さなエクササイズでは、ありがとうございます:) –

関連する問題