【问题标题】:freeing argument in function specified in pthread_create释放 pthread_create 中指定的函数中的参数
【发布时间】:2012-02-01 22:37:17
【问题描述】:

我正在编写一个小型服务器,它创建一个新线程来处理每个新连接。我需要使用 pthread_create 的第四个参数将套接字传递给函数。当试图释放用于套接字的内存时,我得到一个段错误。通讯工作正常。我试过传递一个 void* 和一个 void**(转换为 void*,有点丑)

这是我在尝试解决此问题时使用的最新 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非常缺乏经验。 :)

【问题讨论】:

    标签: c sockets pthreads segmentation-fault


    【解决方案1】:

    您有大量内存泄漏和一般内存错误:

    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】:

      不要分配指针。将socket文件描述符直接传给pthread_create()

      (void*)client_sock
      

      然后,在respond()

      client_sock = (int)thread_arg;
      

      不需要malloc()free()

      【讨论】:

      • 在处理两个并发连接时这不会损坏变量吗?
      • 不,您传递的是变量的值,而不是变量本身。
      • ...假设void* 大到足以容纳int 的所有值,即!
      • 我怀疑它会容纳大多数人。 ;-)
      • 不是int的所有值,只是所有可能的文件描述符。
      【解决方案3】:

      尝试更多类似的东西。

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

      【讨论】:

      • 不要转换malloc()的结果!
      • int 转换为void * 比分配和释放内存要高效得多。
      • 是的,但他只是想知道它为什么会崩溃以及我们是否想要传递更多数据等,他现在知道如何去做了。
      【解决方案4】:
      cs = malloc(sizeof(int));
      cs = (void*)client_sock;
      

      第二个分配使您的代码中出现内存泄漏。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-28
        • 2021-12-03
        • 1970-01-01
        • 2015-03-04
        • 2021-05-22
        • 1970-01-01
        • 2022-01-06
        • 1970-01-01
        相关资源
        最近更新 更多