2017-07-29 121 views
-1

我已閱讀其他類似問題的答案,但它們都不能解決我的問題。LInux中的C socket編程,雙重免費損壞(fasttop)錯誤

這是我的代碼:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <arpa/inet.h> 
#include <errno.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <netdb.h> 
#include <netinet/in.h> 
#include <pthread.h> 

typedef struct { 
    pthread_t thread_id; 
    int sockfd; 
} client_t; 

client_t *clients; 
size_t client_n = 0; 

void *client_thread(void *client_ptr) { 
    client_t client = *(client_t*) client_ptr; 
    char buffer[500]; 
    int state; 
    while(1) { 
    state = send(client.sockfd, 0, 1, MSG_NOSIGNAL); 

    if(state == -1) { 
     printf("socket-%d closed\n", client.sockfd); 
     break; 
    } 

    read(client.sockfd, buffer, 500); 
    printf("from socket-%d: %s\n", client.sockfd, buffer); 
    memset(buffer, 0, 500); 
    } 
    close(client.sockfd); 
    free(client_ptr); 
    client_n--; 
} 

int main(int argc, char *argv[]) { 
    int sockfd, newsockfd, clilen; 
    struct sockaddr_in clientaddr, serveraddr; 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    serveraddr.sin_family = AF_INET; 
    serveraddr.sin_addr.s_addr = INADDR_ANY; 
    serveraddr.sin_port = htons(8080); 

    bind(sockfd, (struct sockaddr*) &serveraddr, sizeof(serveraddr)); 
    listen(sockfd, 5); 

    clilen = sizeof(clientaddr); 

    clients = (client_t*) malloc(sizeof(client_t)); 

    while(1) { 
    newsockfd = accept(sockfd, (struct sockaddr*) &clientaddr, &clilen); 
    printf("New connection: socket-%d\n", newsockfd); 
    clients = (client_t*) realloc(clients, (client_n + 1) * sizeof(client_t)); 
    clients[client_n].sockfd = newsockfd; 
    pthread_create(&clients[client_n].thread_id, NULL, client_thread, (void*) &clients[client_n]); 
    client_n++; 
    } 
    return 0; 
} 

程序應該偵聽傳入的連接,然後創建爲每一個新的線程。該程序將同時處理每個客戶端。由於這應該是遊戲服務器的核心,我創建了一個包含每個玩家信息的結構。

這一切都工作得很好,直到我加入:

close(client.sockfd); 
    free(client_ptr); 
    client_n--; 

任何想法的問題是什麼?

+0

您的分配已損壞。你分配一個'client_t'數組,但是嘗試釋放單個條目,這是不可能的。只需每次分配一個條目,將其分配給客戶端線程,以便將其釋放。 –

回答

2

隨着

free(client_ptr); 
client_n--; 

有問題。

第一個是撥打free。你實際上沒有撥malloc(或realloccallocclient_ptr。而是client_ptr指向您動態分配的數組,但client_ptr指向的元素本身並不是單獨動態分配的。這會導致未定義的行爲當您將指針傳遞給free時,實際上沒有與malloc和系列一起分配。 除了第一個元素(即clients[0]),當你改爲釋放整個數組。解決方法是在線程中不要調用free

另一個問題是client_n--表達式。您不保護此操作(或main函數中的相應client_n++)不受其他線程修改。這意味着兩個或多個線程可能會同時再次修改,導致未定義的行爲。你需要有一個信號量或互斥量來保護這個修改。


還有一些其他問題。例如,您不加入已結束的線程,導致資源泄漏。您不檢查來自read呼叫的錯誤或關閉連接(通過返回0read呼叫報告一個很好的關閉連接)。