2016-05-26 6 views
2

私はC++で構造体を使用していますが、その構造体にポインタを保存しようとしますが、その構造体をスレッドで使用しようとすると構造体のデータを取得できません。Pthreads and Structures C++

struct threadData { 
    void* memPointer; 
    void* instructionPointer; 
    void* stackPointer; 
    int memsize; 
}; 

void *worker_thread(void *arg) { 
    struct threadData *my_data; 
    my_data = (struct threadData *) arg; 
    cout<<"INSTRUCTION POINTER: "<<my_data->instructionPointer<<endl; 
    cout<<"MEMORY POINTER: "<<my_data->memPointer<<endl; 
    cout<<"STACK POINTER: "<<my_data->stackPointer<<endl; 
    cout<<"MEMORY SIZE: "<<my_data->memsize<<endl; 

} 

int main() { 
    pthread_t my_thread; 
    int ret; 
    struct threadData td = { calloc(1, 32), calloc(1000000, 64),  calloc(34, 4),6475 }; 
    ret = pthread_create(&my_thread, NULL, worker_thread, (void *) &td); 
    pthread_detach(my_thread); 
    //pthread_exit(NULL); 
} 

しかし、私はpthread_detachの後にpthread_exit(NULL)を使用するとき、私は方法「worker_thread」における構造の情報を使用することができます。

+1

C++を使用している場合、構造体を初期化するためにコンストラクタを使用していないのはなぜですか?あなたはCスタイルのキャストも使用していますし、 'struct'キーワードを使ってあなたのstruct型を参照しています(これはC++ではほとんど必要ありません)。これは非常にCのようなC++コードです... – DaoWen

+0

あなたがやろうとしていることのC++ 11実装:http://coliru.stacked-crooked.com/a/f0b3dadb23bd7bba – kfsone

+1

@kfsoneあなたはまだcalloc呼び出しを置き換えるかもしれませんそれを完全にC++のようにするには、 'new char [x * y]'を使ってください。完全性のために、私はまだ割り当てられたデータを解放/削除します。確かに、ここでは必要ではありませんが、割り当てられたメモリを最初から破棄することを前に考えると、いつかメモリリークが発生するのを防ぐことができます。 – Aconcagua

答えて

2

pthread_exitを指定しないと、mainから戻ってきます。ローカル変数tdは、他のスレッドが完了する前に破棄されます。

pthread_exitを呼び出すと、他のスレッドが完了するまでメインスレッドが強制的に終了するので、tdはあまりに早く破棄されません。

@Aconcaguaが認識しているように、pthread_exitのドキュメントでは、呼び出し元のスレッドが終了していると表示されています。メインスレッドの例外は発生しません。少なくとも、原則として、メインスレッドのスタックは、他のスレッドがまだ実行されている間に消える可能性があります。つまり、pthread_exitを呼び出しても、未定義の動作が発生します。

+0

[pthread_exitのマニュアルページ](http://man7.org/linux/man-pages/man3/pthread_exit.3.html)から: "retvalが指し示す値は、呼び出しスレッドのスタックに置くべきではありません。スレッドの終了後にそのスタックの内容は未定義です。 "これがメインスレッドにも当てはまる場合、同じことがtdに適用され、他のスレッド内のtdにアクセスすると未定義の動作が発生します。 – Aconcagua

+0

@Aconcagua:この場合、 'retval'(pthread_exitへの引数)がNULLになるため、あなたが作成しようとしている箇所がわかりません。 –

+1

重要な点はretvalではありませんが、スタックは未定義になります - この場合は 'td'です。したがって、他のスレッドから 'td'にアクセスすると、未定義の動作になります(ただし、メインスレッドから呼び出された場合、pthread_exitの動作が異なりますが、リンクのヒントはありません)。 – Aconcagua

3

maintdがスタックに割り当てられているため、mainから返された後に実行時に実行されるクリーンアップコードによって壊れてしまいます。ヒープ上ではなく、スタック上にあなたのtd構造体を割り当て、そして期待どおりに動作します:

struct threadData tdVal = { calloc(1, 32), calloc(1000000, 64),  calloc(34, 4),6475 }; 
struct threadData *td = malloc(sizeof(*td)); 
*td = tdVal; 
// ... 
ret = pthread_create(&my_thread, NULL, worker_thread, (void *) td); 

しかし、あなたはまだ問題を抱えています。 Returning from main will kill the other pthreads in your programworker_threadを実行する前にmainが完了しないようにコードに同期がないため、worker_threadがまったく実行されないことさえありません。

あなたはおそらくないは、ワーカースレッドを取り外し、代わりにそれはmainから復帰する前に完了していることを確認するためにpthread_joinを使用する必要があります。 mainworker_threadが完了する前に返されないようにする場合は、tdをスタックに残しても問題ありません。

+0

pthread_joinを使用している場合は、スタックにtdを持つことに問題はありません。 – Aconcagua

+0

@Aconcagua - はい、ありがとうございます。私はその点を明確にするために答えを更新しました。 – DaoWen