调用者使用未初始化char指针,子函数分配网络数据包内存的段错误修复与端口值传递实现
解决C语言网络数据包构建中的段错误问题
我看到你在构建网络数据包时遇到了段错误,问题出在结构体指针的偏移计算逻辑错误上。让我一步步帮你修正代码并解释原因:
问题根源
当你使用结构体指针(比如struct ethhdr *eth)进行eth + sizeof(struct ethhdr)这样的操作时,C语言会把偏移量当成「结构体个数」来计算,而不是字节数。也就是说,实际偏移的字节数是sizeof(struct ethhdr) * sizeof(struct ethhdr),这远远超出了你malloc分配的内存范围,直接触发了非法内存访问的段错误。
修改后的完整代码
#include <stdio.h> #include <stdlib.h> #include <net/ethernet.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <arpa/inet.h> // 提供htons/ntohs字节序转换函数 void abc(char **c) { // 计算总内存大小:各头部 + payload size_t total_size = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct tcphdr) + 1000; *c = (char *)malloc(total_size); if (*c == NULL) { // 必须检查malloc是否成功,避免空指针访问 perror("malloc failed"); return; } // 正确的指针偏移方式:先转char*,再按字节数偏移(char*步长为1字节) struct ethhdr *eth = (struct ethhdr *)*c; struct iphdr *ip = (struct iphdr *)((char *)eth + sizeof(struct ethhdr)); struct tcphdr *tcp = (struct tcphdr *)((char *)ip + sizeof(struct iphdr)); // 填充TCP源端口:用htons转换为网络大端字节序(符合协议规范) tcp->source = htons(80); printf("abc函数内打印TCP源端口:%d\n", ntohs(tcp->source)); } int main(){ char *pay = NULL; abc(&pay); if (pay == NULL) { // 检查abc函数是否成功分配内存 return 1; } // main函数内同样修正指针偏移逻辑 struct ethhdr *eth = (struct ethhdr *)pay; struct iphdr *ip = (struct iphdr *)((char *)eth + sizeof(struct ethhdr)); struct tcphdr *tcp = (struct tcphdr *)((char *)ip + sizeof(struct iphdr)); printf("main函数内打印TCP源端口:%d\n", ntohs(tcp->source)); // 释放malloc分配的内存,避免内存泄漏 free(pay); return 0; }
关键修正点说明
指针偏移的正确姿势:
把结构体指针强制转换为char*后再加上字节数,因为char*的步长是1字节,这样就能精准地按字节偏移到下一个头部的起始位置,彻底避免越界访问。增加内存分配检查:
永远不要假设malloc一定会成功,加上错误检查能避免后续空指针访问的崩溃问题。字节序规范处理:
网络协议中的端口号是大端字节序,而大部分主机是小端字节序。用htons(80)把主机字节序的80转换成网络字节序存储,读取时用ntohs()转换回主机字节序再打印,这样结果才符合预期且符合协议规范。修复内存泄漏:
在main函数末尾用free(pay)释放malloc分配的内存,避免程序退出后残留内存泄漏。
内容的提问来源于stack exchange,提问作者user786
相关产品推荐
相关产品推荐

