2012-03-09 8 views
0


私はおそらく(SIGSEGV)エラーが発生するため、fpのポインタの問題があります。 しかし私はCであまり経験はありませんし、私はそれを見ません。ポインタの構造体の問題

私がやろうとしていること。私は単純なゲームのためのサーバーアプリケーションを行う、私は新しいスレッドでクライアントを処理します。私は関数pthread_createを使用し、handle_clientというハンドル関数を持っています。いくつかのargumets socketdescritpor(動作します)とログを書き込むためのfiledescriptor(おそらく問題があります)を取得する必要があります。 私のメインではログファイルを開いて、私は構造体にfiledescriptorを入れ、handle_client関数内に構造体を入れ、この関数でログファイルのファイルデクリプタ(fp)を取得したいファイルに書き込む。私は各fprintfの後にデータを保存するためにfflush(fp)を使います。ファイルを一度開き、各クライアントがこのdescriporをファイルに書き込むことができるはずですが、おそらくポインターで何か悪いことをしました(私はfpを構造体から出て、私がこのアクションを行うところに私のコードがあります。)Thx for help。

構造体

typedef struct 
    { 
     int fd; 
     FILE *fp; //filepointer for logs file 
    } my_thread_context_t; 

メイン

int main(int argc, char *argv[]) { 
FILE * fp; 
    fp = fopen("Serverlog.log","w");//delete last file 
    fclose(fp); 
    fp = fopen("Serverlog.log","a+"); 
     my_thread_context_t ctx; 

//bind server 
//listen 

while(1) { 
//accept 

ctx.fp = fp;// add file pointer to structure 
int check = pthread_create(&thread, NULL,handle_client,&ctx); 
//other code 
} 

hadle_client機能

void * handle_client(void * void_context){ 
    my_thread_context_t * context = (my_thread_context_t *) void_context; 

    FILE *fp; //pointer na soubor s logy 
    fp = context->fp;//get the filepointer for logs 

     //other code .. 

} 
+2

デバッガでプログラムを実行しようとしましたか?クラッシュの位置を特定するのに役立ちます。また、何が間違っているかを見るのに役立つ変数を調べるのに役立ちます。 –

+1

'gdb'や他のデバッガを使ってコードが失敗する箇所を知ることができます。また、エラーを分離するには、最初に疑わしいコードセグメントをスレッドなしで実行してください。 – phoxis

+0

一般に、あるスレッドでファイルを開き、別のスレッドからファイルを処理するには、奇妙なプログラム設計が行われます。私はちょうど推測していますが、お使いのOSの内部動作に応じて、これが原因かもしれません。スレッド内からファイルを開こうとします。また、fopen()、fprintf()などの関数はスレッドセーフではないので、それらを使って複数のスレッドを持つことはできません。 – Lundin

答えて

2

多くのスレッドが正確に問題であなたのmy_thread_context_t::fpにアクセスできるように見えます。 FILE*タイプは、実際にはCライブラリで使用される構造体への(不透明な)ポインタです。複数のスレッドが複数のスレッドを変更した場合、この構造の内容が壊れてしまう(または非一貫性がある)ことがあります。 my_thread_context_t::fpへのアクセスを同期する必要があります。 ctx構造内にmutex(pthread_mutex_initpthread_mutex_lockpthread_mutex_unlock)を作成することをお勧めします。各スレッドは、それがファイルへの書き込みを開始する前にそれをロックし、その完成書き込み時にロックを解除する必要があります - このpuprposeに別々の(インライン)関数はさらに良いデザインだろう、例えば:

typedef struct 
{ 
    int fd; 
    pthread_mutex_t mutex; 
    FILE *fp; //filepointer for logs file 
} my_thread_context_t; 

my_thread_context_t ctx; 
fp = fopen("Serverlog.log","a+"); 
pthread_mutex_init(&ctx.mutex); 
ctx.fp = fp; 

inline void write_to_log(my_thread_context_t* pCtx,const char* pcszMessage) 
{ 
    pthread_mutex_lock(&(pCtx->mutex)); 
    /* here write to the log file */ 
    pthread_mutex_unlock(&(pCtx->mutex)); 
} 

あなたはこのようにそれを行うとそれだけでは安全ではありませんが、ログを常に同期しない限り、書き込みごとにfflush を呼び出す必要はありません。

すべてのスレッドが終了した後に、pthread_mutex_destroyに電話することを忘れないでください(たとえば、すべての必要が生じた後にptrhead_join)。