C语言多线程Web服务器触发SIGABRT错误求助
问题
我是C语言新手,正在搭建一个简易Web服务器作为入门项目,但在正确返回HTML文件、处理完一个请求后,handleClient函数触发了SIGABRT错误。该错误是在引入Posix线程后出现的,我推测这与多线程和错误的内存处理有关,希望有人能为我指引排查方向,或是指出代码中可能存在的问题。
代码实现
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <fcntl.h> #include <pthread.h> void serveFile(int socket, const char* filename) { char buffer[1024]; int fd; int readBytes; fd = open(filename, O_RDONLY); if (fd == -1) { perror("File open failed"); return; } while ((readBytes = read(fd, buffer, sizeof(buffer))) > 0) { write(socket, buffer, readBytes); } close(fd); } void *handleClient(void *arg) { int socket = *(int*)arg; char buffer[1024]; int readBytes; readBytes = read(socket, buffer, sizeof(buffer)); buffer[readBytes] = '\0'; printf("Received: %s\n", buffer); char *header = "HTTP/1.1 200 OK\nContent-Type: text/html\n\n"; write(socket, header, strlen(header)); serveFile(socket, "./helloworld.html"); close(socket); free(arg); return NULL; } int main() { int server_fd, new_socket; struct sockaddr_in address; int opt = 1; int addrlen = sizeof(address); if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) { perror("bind failed"); exit(EXIT_FAILURE); } if (listen(server_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } while(1) { printf("Waiting for connections...\n"); int *client_fd = malloc(sizeof(int)); if ((*client_fd = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); continue; } pthread_t thread_id; if(pthread_create(&thread_id, NULL, handleClient, (void *)client_fd)) { perror("Could not create thread"); continue; } pthread_detach(thread_id); } return 0; }
补充信息
- 服务器收到的客户端请求:
Received: GET / HTTP/1.1 Host: localhost:8080 Connection: keep-alive Cache-Control: max-age=0 sec-ch-ua: "Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "macOS" Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-US,en;q=0.9,sv-SE;q=0.8,sv;q=0.7 Cookie: access_token="token"
- 运行环境:搭载M3芯片的macOS系统,使用最新版Chrome测试
- 错误信息:
zsh: abort ./http_server
排查与修复方案
1. 核心崩溃原因:数组越界访问
handleClient中直接使用read的返回值作为数组下标,但**read可能返回-1(读取失败)**,此时buffer[readBytes] = '\0'会变成buffer[-1] = '\0',触发内存访问错误,直接导致SIGABRT。
修复代码:
readBytes = read(socket, buffer, sizeof(buffer) - 1); // 预留1字节存终止符 if (readBytes == -1) { perror("Read failed"); close(socket); free(arg); return NULL; } buffer[readBytes] = '\0';
2. 内存泄漏问题
main函数中malloc了client_fd,但如果accept调用失败,直接continue会导致这块内存无法释放,长期运行会耗尽系统内存。
修复代码:
int *client_fd = malloc(sizeof(int)); if ((*client_fd = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("accept"); free(client_fd); // 释放已分配的内存 continue; }
3. 线程安全优化(可选)
多线程同时调用printf会导致输出混乱,虽然不会触发崩溃,但可以用互斥锁保证输出有序:
// 在全局区域定义互斥锁 pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER; // 在handleClient的printf前后加锁解锁 pthread_mutex_lock(&print_mutex); printf("Received: %s\n", buffer); pthread_mutex_unlock(&print_mutex);
4. write返回值处理(可选)
write可能因网络问题返回-1或写入不完整,建议添加基础检查避免响应发送不完整:
ssize_t writeBytes = write(socket, header, strlen(header)); if (writeBytes == -1) { perror("Write header failed"); }
内容的提问来源于stack exchange,提问作者Jacob
相关产品推荐
相关产品推荐

