2012-01-03 10 views
2

新しい接続を処理するための新しいスレッドを作成する小さなサーバーを作成しています。 pthread_createの第4引数を使用して関数にソケットを渡す必要があります。ソケットに使用されているメモリを解放しようとすると、segfaultが発生します。コミュニケーションはうまくいきます。私はvoid *とvoid **をキャストしようとしました。(void *、一種の醜いキャスト)pthread_createで指定された関数の引数を解放する

これは私がこれを理解しようとしている間に使っている最新のクルージであり、応答機能では

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <stdio.h> 
#include <pthread.h> 

void *respond(void *thread_arg) 
{ 
     void *arg = *(void**)thread_arg; 
     printf("responding...\n"); 
     int client_sock; 
     client_sock = (int)arg; 

     char *message = "Write smthng to echo!\n\t"; 
     send(client_sock,message,strlen(message),0); 
     char *buf = (char*)malloc(100); 
     int ptr = 0; 
     char last = ' '; 
     while (last != '\n') { 
       recv(client_sock,&last,1,0); 
       buf[ptr++] = last; 
     } 
     buf[ptr++] = '\n'; 
     send(client_sock, buf, ptr, 0); 
     ptr = 0; 
     free(buf); 
     close(client_sock); 
     //free(arg); // why segfault? 
     //free(*(void**)thread_arg); // the same 
     pthread_exit(NULL); 
} 

int main(int argc, char **argv) 
{ 
     int socket_desc, client_sock, addrlen, tmp; 
     struct sockaddr_in address; 
     pthread_t *responder_thread; 
     void *cs; 

     socket_desc = socket(AF_INET, SOCK_STREAM, 0); 
     if (socket_desc < 0) 
       printf("could not create socket"); 
     address.sin_family = AF_INET; 
     address.sin_addr.s_addr = INADDR_ANY; 
     address.sin_port = htons(8080); 
     tmp = bind(socket_desc, (struct sockaddr *)&address, sizeof(address)); 
     if (tmp < 0) 
       printf("could nod bind to port!"); 
     listen(socket_desc, 5); 

     addrlen = sizeof(struct sockaddr_in); 
     while (true) { 
       client_sock = accept(socket_desc, (struct sockaddr *)&address, (socklen_t*)&addrlen); 
       if (client_sock < 0) { 
         printf("could not create client socket"); 
       } else { 
         printf("Accepted connection!\n"); 
         cs = malloc(sizeof(int)); 
         cs = (void*)client_sock; 
         responder_thread = (pthread_t*)malloc(sizeof(pthread_t*)); 
         tmp = pthread_create(responder_thread, NULL, respond, (void*)&cs); 
         //cs = NULL; 
         if (tmp) { 
           printf("pthread_create returned '%d', exiting", tmp); 
           exit(-1); 
         } 

       } 
     } 
     pthread_exit(NULL); 
} 

最後に、明確にするために、私は非常に不慣れです。 :)

答えて

1

これ以上のようなものを試してみてください。

int* cs; 
... 
cs = (int*)malloc(sizeof(int)); 
*cs = client_sock; 
... 
tmp = pthread_create(responder_thread, NULL, respond, (void*)cs); 

このキャストは必要ありません。

void *arg = *(void**)thread_arg; 

あなたはthread_argを解放することができます。

free(thread_arg); 
+0

これはトリックでした。ありがとうございました。 – tommyo

+2

'malloc()'の結果をキャストしないでください! –

+0

'int'を' void * 'にキャストするだけで、メモリの割り当てや解放よ​​りもずっと効率的です。 –

1
cs = malloc(sizeof(int)); 
cs = (void*)client_sock; 

2番目の割り当てによって、コードにメモリリークが発生します。

3

あなたは大量のメモリリークおよび一般的なメモリエラーを有する:最初の行はメモリを割り当て、csにポインタを割り当て、2行目は直ちにで上書きすることによって、そのポインタを捨てる

cs = malloc(sizeof(int)); 
cs = (void*)client_sock; 

を積分値client_sock。後での値で解放しようとします。これは有効なポインタではないため、致命的なエラーです。

あなたはこのようなあなたのコードを構造化する必要があります。

int * cs = malloc(sizeof(int)); 
*cs = client_sock; 
pthread_create(..., cs); 

とスレッド機能:

void * respond(void * thread_arg) 
{ 
    int * cs = (int*)thread_arg; 
    /* ... */ 
    free(cs); 
} 

csのアドレスを取ることによって、余分な間接の必要はありません。

2

ポインタを割り当てないでください。 pthread_create()に直接ソケットファイルディスクリプタを渡します

その後
(void*)client_sock 

respond()に:

client_sock = (int)thread_arg; 

ないmalloc()free()必要。

+0

これは2つの同時接続を処理するときに変数を破壊しませんか? – tommyo

+1

いいえ、変数自体ではなく、変数の値を渡しています。 –

+0

...'void *'が 'int'のすべての値を保持するのに十分な大きさであると仮定すると、つまり! –

関連する問題