2012-01-03 43 views
2

我正在寫一個小型服務器,它創建一個處理每個新連接的新線程。我需要使用pthread_create的第四個參數將套接字傳遞給函數。當試圖釋放用於套接字的內存時,我得到一個段錯誤。溝通工作正常。我嘗試過傳遞一個void *和一個void **(被鑄造爲void *,有點難看)在pthread_create中指定的函數中釋放參數

這是我在試圖弄清楚這個時候使用的最新的cludge,稍後如果將會做實際的工作在響應函數中。

#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); 
} 

最後,澄清;在c方面我很缺乏經驗。 :)

回答

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 2012-01-03 23:24:35

+2

不要施加'malloc()'的結果! – 2012-01-03 23:35:33

+0

只需將'int'強制轉換爲'void *'將比分配和釋放內存更有效。 – 2012-01-04 00:45:22

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

第二個賦值讓你在你的代碼中有內存泄漏。

3

你有一個巨大的內存泄漏和一般的內存錯誤:

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

第一行分配內存和指針分配給cs,第二行立即與覆蓋它扔掉該指針積分值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

當處理兩個併發連接時,這不會破壞變量嗎? – tommyo 2012-01-03 23:20:08

+1

不,您正在傳遞變量的值,而不是變量本身。 – 2012-01-03 23:21:26

+0

...假設'void *'足夠大以保存'int'的所有值,那就是! – 2012-01-03 23:23:20