创建Socket时触发Segmentation Fault段错误问题求助
问题排查与修复方案
1. 打印语句不显示的根因
标准输出stdout默认是行缓冲模式,只有遇到换行符\n、缓冲区满或者程序正常退出时才会将缓冲区内容输出到屏幕。你的代码中printf("Here I Am0")这类语句没有加换行符,内容卡在缓冲区内还没输出就触发了段错误,所以你看不到这些打印,误以为代码没执行。
修复方式:所有调试用printf末尾加\n,或者每次打印后调用fflush(stdout)强制刷新缓冲区,就能看到准确的执行位置。
2. 段错误的几个触发点
(1)日志文件指针空引用
你设置了useLog = 0,所以不会执行fopen打开日志文件,logfile一直保持初始的NULL值。如果你后续的代码(节选部分没贴出的内容)中存在fprintf(logfile, xxx)这类写入日志的操作,传入空的文件指针会直接触发段错误。
修复方式:所有对logfile的读写操作都要包裹在if (useLog == 1)的判断中,避免空指针引用。另外你当前的日志文件存在误报问题,判断文件是否打开失败的逻辑应该挪到fopen之后:
if (useLog == 1){ printf("Using Log File\n"); logfile = fopen("log.txt","w"); if(!logfile) { printf("Unable to create log.txt file. \n"); } }
(2)socket创建失败未做校验
SOCK_RAW类型的socket即使使用sudo运行也有可能创建失败,返回值为-1。如果后续直接把非法的文件描述符传入setsockopt或者后续的收发包函数,会触发异常。
修复方式:创建socket后立刻做合法性校验:
int sock_raw = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock_raw < 0) { perror("socket创建失败"); exit(EXIT_FAILURE); }
(3)网卡名不匹配
你代码中硬编码绑定的网卡是wlan0,现在多数Linux发行版的网卡命名规则已经变更,无线网卡常见名称是wlpXXX格式,有线网卡常见是ensXXX格式,如果网卡名不存在,setsockopt会调用失败,后续操作也可能触发异常。
修复方式:执行ip a命令查看你当前可用的网卡名称,替换代码中的wlan0,同时对setsockopt的返回值做校验:
const char* nic_name = "替换为你的实际网卡名"; if (setsockopt(sock_raw, SOL_SOCKET, SO_BINDTODEVICE, nic_name, strlen(nic_name) + 1) < 0) { perror("绑定网卡失败"); close(sock_raw); exit(EXIT_FAILURE); }
(4)malloc返回值未校验
你申请了65536字节的缓冲区,没有判断malloc的返回值,如果内存分配失败返回NULL,后续往缓冲区写入数据时会触发段错误。
修复方式:增加malloc校验:
unsigned char *buffer = malloc(65536); if (buffer == NULL) { perror("内存分配失败"); exit(EXIT_FAILURE); }
调试建议
按以上方案修改后如果还有问题,可以用gdb工具定位段错误位置:
- 编译时加
-g参数:gcc -g test.c - 用gdb运行:
sudo gdb ./a.out - gdb内输入
run启动程序,崩溃后输入bt就能看到完整的调用栈,直接定位到触发段错误的代码行。
内容的提问来源于stack exchange,提问作者Lyra Orwell
相关产品推荐
相关产品推荐

