分段错误将指针传递给函数

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;

函数参数packetconst unsigned char *,因此该语句将其指向的单个unsigned char 的值转换为一个指针,然后将该指针用作指向struct ip。这几乎肯定会产生未定义的行为,因为它违反了严格的别名规则,并且它产生您实际想要的行为的可能性基本上为零。改为这样做:

struct ip *ip_header = (struct ip*) packet;

但也请注意,将结构类型映射到原始字节数组是一项棘手的工作。获得正确的成员顺序和数据类型通常并不难,但 C 允许结构布局在结构成员之间(和之后)包含任意填充。特别是,尽管大多数 C 实现都提供了避免这种情况的机制,但没有标准机制。

在这种情况下,您会遇到双重问题。不仅您的struct ipstruct ether_header 受此约束,系统的struct in_addr 也受此约束。尽管您可以控制自己结构的声明,但假设您可以将 struct in_addr 映射到原始数据包数据上是危险的,就像您为 inet_ntoa 生成参数一样。

【讨论】:

知道我是愚蠢的。感谢您的简洁回答!

以上是关于分段错误将指针传递给函数的主要内容,如果未能解决你的问题,请参考以下文章

将指向数组的指针传递给函数时出现分段错误(C++)

通过指针或引用将映射传递给函数?

Int 指针不为空,可以打印,但不能在不引发分段错误的情况下传递给函数

将指向 int 数组的指针传递给成员函数,错误:数组下标的无效类型“int [int]”

无法将指向派生类函数的指针传递给基类

将结构指针向量对的值传递给函数