分段错误将指针传递给函数
Posted
技术标签:
【中文标题】分段错误将指针传递给函数【英文标题】:segmentation fault passing pointer to function 【发布时间】:2017-10-31 13:20:52 【问题描述】:因此,从 parseEther 方法调用 parseIP 函数时会发生分段错误。 我真的不知道为什么会出现分段错误,我只是在获取数据包指针并添加以太网标头的长度 (14)。 打印地址的输出为我提供了相隔 14 的十六进制地址,因此我知道指针指向内存中的正确位置。尽管如此,当我通过它时仍然会遇到分段错误? 我是否遗漏了一些非常明显的东西? 示例输出: https://s1.postimg.org/96owsptn8v/seg_fault.png编辑 我只是从 parseIP 中取出代码并将其放入调用它的 if 语句中,它工作得非常好。真的很奇怪。有人知道吗?
void parseIP(const unsigned char *packet)
printf("before we cast ip header");
struct ip *ip_header = (struct ip*) *packet;
printf("Before we initialise length");
short length = ip_header -> ip_len;
printf("Before we initialise headerlength");
int headerlength = ntohs(ip_header-> ip_hl); //iphdr points to header of network packet
printf("No segmentation fault here! \n");
printf("\n Source Ip address \n");
printf("%s", inet_ntoa(ip_header -> ip_src));
printf("\n Destination Ip address \n");
printf("%s", inet_ntoa(ip_header -> ip_dst));
int data_bytes = length - headerlength;
const unsigned char *payload = packet + headerlength;
void parseEther(const unsigned char *packet, int length)
int i;
int pcount = 0;
struct ether_header *eth_header = (struct ether_header *) packet;
printf("\n\n === PACKET %ld HEADER ===", pcount);
printf("\nSource MAC: ");
for (i = 0; i < 6; ++i)
printf("%02x", eth_header->ether_shost[i]);
if (i < 5)
printf(":");
printf("\nDestination MAC: ");
for (i = 0; i < 6; ++i)
printf("%02x", eth_header->ether_dhost[i]);
if (i < 5)
printf(":");
int data_bytes = length - ETH_HLEN;
printf(" \n total length - %d -- length of header - %d -- remaining length - %d \n", length, ETH_HLEN, data_bytes);
printf("Packet address - %p\n", packet);
const unsigned char *payload = packet + ETH_HLEN;
printf("Payload address - %p\n", payload);
//payload pointer now points to start of the network header
printf("\nType: %d\n", ntohs(eth_header->ether_type));
if(ntohs(eth_header->ether_type) == 0x0806)
printf("ARP detected \n");
// parseARP(payload);
else if(ntohs(eth_header->ether_type) == 0x0800)
printf("\nIP detected\n");
parseIP(payload);
【问题讨论】:
struct ip *ip_header = (struct ip*) *packet;
好像很奇怪
怎么样?无论如何,程序不会在 seg 错误之前打印“before we cast ip header”,所以它必须在之前。 edit 刚刚记录了双 *.哎呀
我认为struct ip *ip_header = (struct ip*) *packet;
应该是struct ip *ip_header = (struct ip*) packet;
... packet
不是指针的指针!
【参考方案1】:
我是否遗漏了一些非常明显的东西?
我想这取决于你的明显标准,但肯定这是错误的:
struct ip *ip_header = (struct ip*) *packet;
函数参数packet
是const unsigned char *
,因此该语句将其指向的单个unsigned char
的值转换为一个指针,然后将该指针用作指向struct ip
。这几乎肯定会产生未定义的行为,因为它违反了严格的别名规则,并且它产生您实际想要的行为的可能性基本上为零。改为这样做:
struct ip *ip_header = (struct ip*) packet;
但也请注意,将结构类型映射到原始字节数组是一项棘手的工作。获得正确的成员顺序和数据类型通常并不难,但 C 允许结构布局在结构成员之间(和之后)包含任意填充。特别是,尽管大多数 C 实现都提供了避免这种情况的机制,但没有标准机制。
在这种情况下,您会遇到双重问题。不仅您的struct ip
和struct ether_header
受此约束,系统的struct in_addr
也受此约束。尽管您可以控制自己结构的声明,但假设您可以将 struct in_addr
映射到原始数据包数据上是危险的,就像您为 inet_ntoa
生成参数一样。
【讨论】:
知道我是愚蠢的。感谢您的简洁回答!以上是关于分段错误将指针传递给函数的主要内容,如果未能解决你的问题,请参考以下文章
Int 指针不为空,可以打印,但不能在不引发分段错误的情况下传递给函数