Valgrind在c中读取大小为4的链表无效



我在C中遇到了一些链表问题。我实际上正在做一个项目使用套接字连接与服务器和客户端。我决定为我的客户使用链表。这是我的结构:

typedef struct ClientsList_s {
int sockfd;
struct ClientsList_s *next;
} ClientsList_t;

所以,当我用valgrind执行我的工作时,我从6个上下文中得到了6个错误。下面是一个错误示例:

Invalid read of size 4
==33211==    at 0x109531: get_max_socket (server.c:26)
==33211==    by 0x1097C2: do_server_loop (server.c:80)
==33211==    by 0x109A40: launch_teams (main.c:53)
==33211==    by 0x109AE6: main (main.c:63)
==33211==  Address 0x4a58040 is 0 bytes inside a block of size 16 free'd
==33211==    at 0x483CA3F: free (in /usr/lib/x86_64-linux- 
gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==33211==    by 0x109675: receive_socket_message (server.c:47)
==33211==    by 0x109832: do_server_loop (server.c:86)
==33211==    by 0x109A40: launch_teams (main.c:53)
==33211==    by 0x109AE6: main (main.c:63)
==33211==  Block was alloc'd at
==33211==    at 0x483B7F3: malloc (in /usr/lib/x86_64-linux- 
gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==33211==    by 0x10937B: add_client (client.c:18)
==33211==    by 0x109777: check_new_socket (server.c:68)
==33211==    by 0x109816: do_server_loop (server.c:84)
==33211==    by 0x109A40: launch_teams (main.c:53)
==33211==    by 0x109AE6: main (main.c:63)

这是错误产生的函数:

static int get_max_socket(MasterSocket_t *server, ClientsList_t **clients)
{
int maxSd = server->sockfd;
ClientsList_t *temp = *clients;
FD_ZERO(&server->readfds);
FD_SET(server->sockfd, &server->readfds);
while (temp != NULL) {
if (temp->sockfd > 0)
FD_SET(temp->sockfd, &server->readfds);
if (temp->sockfd > maxSd)
maxSd = temp->sockfd;
temp = temp->next;
}
return (maxSd);
}

因此,当我关闭客户端而服务器仍在运行时,所有错误都会出现。我在while语句中使用temp的每一行都会给我一个错误。一开始我以为这是一个初始化问题但它似乎不是。下面是我的函数:

void add_client(ClientsList_t **clients, int newSocket, int port)
{
ClientsList_t *temp = NULL;
ClientsList_t *last = *clients;
temp = malloc(sizeof(ClientsList_t));
temp->sockfd = newSocket;
temp->next = NULL;
if (*clients == NULL)
*clients = temp;
else {
while (last->next != NULL)
last = last->next;
last->next = temp;
}
}

还有一个函数,当我关闭他的客户端时,我销毁了一个元素:

static void receive_socket_message(ClientsList_t **clients,
MasterSocket_t *server)
{
ClientsList_t *temp = *clients;
ClientsList_t *tempDel = NULL;
int valread = 0;
int addrlen = 0;
char buffer[1025];
while (temp != NULL) {
if (FD_ISSET(temp->sockfd, &server->readfds)) {
if ((valread = read(temp->sockfd, buffer, sizeof(buffer))) == 0) {
tempDel = temp;
temp = temp->next;
close(tempDel->sockfd);
free(tempDel);
continue;
} else {
buffer[valread] = '';
printf("%sn", buffer);
}
}
temp = temp->next;
}
}

如果你想测试什么,这里有一个循环函数:

static int check_new_socket(ClientsList_t **clients,
MasterSocket_t *server, int port)
{
int newSocket = 0;
if (FD_ISSET(server->sockfd, &server->readfds)) {
if ((newSocket = accept(server->sockfd,
(struct sockaddr *)&server->address,
(socklen_t *)&server->addrlen)) < 0)
return (-1);
add_client(clients, newSocket, port);
}
return (0);
}
int do_server_loop(MasterSocket_t server, int port)
{
int maxSd = 0;
int activity = 0;
ClientsList_t *clients = NULL;
while (true) {
maxSd = get_max_socket(&server, &clients);
if ((activity = select(maxSd + 1, &server.readfds,
NULL, NULL, NULL)) < 0 
&&  (errno != EINTR))
return (-1);
if (check_new_socket(&clients, &server, port) == -1)
return (-1);
receive_socket_message(&clients, &server);
}
destroy_clients(clients);
return (0);
}

谢谢你的帮助。

问题是在receive_socket_message中:当您释放列表元素时,您不会将前一个节点链接到下一个节点。

修改后的版本:

static void receive_socket_message(ClientsList_t **clients,
MasterSocket_t *server)
{
ClientsList_t *temp = *clients;
ClientsList_t *tempDel = NULL;
ClientsList_t **link = clients;
int valread = 0;
int addrlen = 0;
char buffer[1025];
while (temp != NULL) {
if (FD_ISSET(temp->sockfd, &server->readfds)) {
if ((valread = read(temp->sockfd, buffer, sizeof(buffer))) == 0) {
tempDel = temp;
*link = temp = temp->next;
close(tempDel->sockfd);
free(tempDel);
continue;
} else {
buffer[valread] = '';
printf("%sn", buffer);
}
}
link = &temp->next;
temp = temp->next;
}
}

最新更新