gpt4 book ai didi

c - pthread_create 内存泄漏

转载 作者:行者123 更新时间:2023-11-30 14:52:19 34 4
gpt4 key购买 nike

我正在尝试编写一个非常基本的多线程 TCP 客户端服务器系统,并设法使主要功能正常工作,并解决了除一个之外的所有内存问题。

当服务器关闭时,我将其设置为接收和处理 SIGINT 信号,该信号将关闭监听和 connfd 以及执行一些任意输出。

问题是 valgrind 在退出时报告内存泄漏,它说这是来自 pthread_create 并且线程在退出时保持事件状态。对于当时每个连接的用户来说,泄漏的大小为 272 字节。

Valgrind output

sig 处理程序和 main 的代码如下:

struct timeval t1, t2;
int connfd = 0;
int listenfd = 0;
pthread_t sniffer_thread;

static void SIGhandler(int sig, siginfo_t *siginfo, void *context)
{

pthread_join(sniffer_thread, NULL);

shutdown(connfd, SHUT_RDWR);
shutdown(listenfd, SHUT_RDWR);

gettimeofday(&t2, NULL);

double totalSeconds = (double) (t2.tv_usec - t1.tv_usec) / 1000000 + (double) (t2.tv_sec - t1.tv_sec) ;

int seconds = ((int)totalSeconds % 60);
int minutes = ((int)totalSeconds % 3600) / 60;
int hours = ((int)totalSeconds % 86400) / 3600;
int days = ((int)totalSeconds % (86400 * 30)) / 86400;

printf("\n\nServer shutdown request received");
printf ("\nTotal server up time = %d days %d hours %d minutes and %d seconds\n\n",days, hours ,minutes , seconds);

close(connfd);
close(listenfd);


exit(EXIT_SUCCESS);
}


int main(void)
{

gettimeofday(&t1, NULL);

struct sigaction act;

memset(&act, '\0', sizeof(act));

// this is a pointer to a function
act.sa_sigaction = &SIGhandler;

// the SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler
act.sa_flags = SA_SIGINFO;

if (sigaction(SIGINT, &act, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}

struct sockaddr_in serv_addr;
struct sockaddr_in client_addr;
socklen_t socksize = sizeof(struct sockaddr_in);
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(50001);

bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));

if (listen(listenfd, 10) == -1) {
perror("Failed to listen");
exit(EXIT_FAILURE);
}
// end socket setup

//Accept and incoming connection
puts("Waiting for incoming connections...");
while (1) {
printf("Waiting for a client to connect...\n\n");
connfd =
accept(listenfd, (struct sockaddr *) &client_addr, &socksize);

printf("\n\nConnection established with: %s\n", inet_ntoa(client_addr.sin_addr));
printf("%s is connected on socket: %d\n",inet_ntoa(client_addr.sin_addr),connfd);


// third parameter is a pointer to the thread function, fourth is its actual parameter
if (pthread_create
(&sniffer_thread, NULL, client_handler,
(void *) &connfd) < 0) {
perror("could not create thread");
exit(EXIT_FAILURE);
}


printf("Handler assigned\n\n");
}

// never reached...
exit(EXIT_SUCCESS);
} // end main()

客户端处理程序代码是:

// thread function - one instance of each for each connected client
void *client_handler(void *socket_desc)
{
pthread_detach(pthread_self());
//Get the socket descriptor
int connfd = *(int *) socket_desc;

send_conConfirm(connfd);


char choice[8];

do {
get_menu_choice(connfd,choice);
switch (*choice) {
case '1':
printf("Executing IP/ID return for socket: %d\n",connfd);
send_studentID(connfd);
break;
case '2':
printf("Executing server time return for socket: %d\n",connfd);
send_serverTime(connfd);
break;
case '3':
printf("Executing sys info return for socket: %d\n",connfd);
send_uname(connfd);
break;
case '4':
printf("Executing file list return for socket: %d\n",connfd);
send_filenames(connfd,choice);
break;
case '5':
send_filenames(connfd,choice);
break;
case '6':
printf("Disconection choice on socket: %d\n",connfd);
break;
default:
printf("Client on socket %d has been disconnected\n", connfd);
goto jump;
break;
}
} while (*choice != '6' );



jump: //jump for goto statement


shutdown(connfd, SHUT_RDWR);
close(connfd);

printf("Thread %lu exiting\n", (unsigned long) pthread_self());

return 0;
} // end client_handler()

我尝试了许多不同的方法,包括在完成后分离线程,但总是以内存泄漏告终。有时,即使客户端仅连接并且服务器结束,也会发生内存泄漏,而其他时候,仅当客户端连接并与服务器交互时才会发生内存泄漏。

最佳答案

您需要在 while 循环结束之前放置一个连接,而不是在信号捕获函数中

我建议您仔细阅读本指南的最后几节,他们处理的代码的一些问题是:

  • 加入线程,以便线程不会因为您正在使用而保持打开状态线程,
  • 你的 connfd 可以被覆盖(因为它存在于同一个文件中)跨不同线程的内存空间)
  • 将 while 循环调整为仅在连接打开时运行(将其更改为在返回接受)

http://www.binarytides.com/socket-programming-c-linux-tutorial/

关于c - pthread_create 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47666459/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com