客户端recevoir_liste_comptines函数出现Segmentation Error求助
问题分析与修复方案
导致段错误的核心问题
- read未添加字符串终止符:
read系统调用不会自动在缓冲区末尾添加'\0',而strtok要求输入是以null结尾的字符串。如果读取的256字节刚好填满buf,strtok会越界访问内存,触发段错误。 - token的错误内存管理:你先给
token分配了堆内存,随后直接将token指向strtok返回的栈内存指针(buf是栈上的数组),导致原堆内存泄漏;最后free(token)时,你试图释放栈内存,这是非法操作,必然引发段错误。 - 循环越界访问:显示列表的循环条件是
i <= comptine_count,但comptines的有效索引是0到comptine_count-1(因为comptine_count是元素数量),访问comptines[comptine_count]属于越界,会触发段错误。 - read的缓冲区大小风险:
buf的大小是BUF_SIZE,但你强制读取256字节,如果BUF_SIZE < 256,会直接溢出栈缓冲区,引发未定义行为。
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdint.h> #define BUF_SIZE 512 // 假设BUF_SIZE定义合理 #define MAX_COMPTINES 100 uint16_t recevoir_liste_comptines(int fd) { char buf[BUF_SIZE]; char** comptines = NULL; uint16_t comptine_count = 0; int i; // 读取时留一个字节给终止符,避免溢出 ssize_t n = read(fd, buf, sizeof(buf) - 1); if (n < 0) { perror("read"); exit(EXIT_FAILURE); } // 手动添加字符串终止符,确保strtok能正常工作 buf[n] = '\0'; // 不需要提前malloc token,直接用strtok返回的指针即可 char *token = strtok(buf, "\n"); while (token != NULL && comptine_count < MAX_COMPTINES) { comptines = realloc(comptines, (comptine_count + 1) * sizeof(char*)); if (comptines == NULL) { perror("realloc"); // 内存分配失败时先释放已分配的元素,避免泄漏 for (int j = 0; j < comptine_count; j++) { free(comptines[j]); } free(comptines); exit(EXIT_FAILURE); } comptines[comptine_count++] = strdup(token); token = strtok(NULL, "\n"); } // 修复循环条件:i < comptine_count,避免越界 for (i = 0; i < comptine_count; i++) { printf("%s\n", comptines[i]); free(comptines[i]); } free(comptines); // 移除错误的free(token),因为token指向栈内存,不能free return comptine_count; }
额外优化说明
- 内存分配失败时增加了资源清理逻辑,避免内存泄漏。
- 读取缓冲区时使用
sizeof(buf)-1,确保不会溢出栈空间,同时预留位置添加终止符。 - 移除了无用的
tokenmalloc操作,避免内存泄漏和非法free操作。
内容的提问来源于stack exchange,提问作者10969_ shirazu_
相关产品推荐
相关产品推荐

