已定义并初始化memcpy上的SegFault以及源和目标

已定义并初始化memcpy上的SegFault以及源和目标,c,linux,C,Linux,通过复制到初始化指针,我得到了SEGFULT。这是相关代码 *pay = (char *)malloc(sizeof(t1) + 1020 /*1000=payload*/); memset(*pay, 0, sizeof(t1) + 1020); struct ethhdr *eth = (struct ethhdr *) *pay; struct iphdr *ip = (struct iphdr *) (*pay + sizeof(struct ethhdr)); struct tcphd

通过复制到初始化指针,我得到了SEGFULT。这是相关代码

*pay = (char *)malloc(sizeof(t1) + 1020 /*1000=payload*/);
memset(*pay, 0, sizeof(t1) + 1020);
struct ethhdr *eth = (struct ethhdr *) *pay;
struct iphdr *ip = (struct iphdr *) (*pay + sizeof(struct ethhdr));
struct tcphdr *tcp = (struct tcphdr *) (*pay + sizeof(struct ethhdr) + sizeof(struct iphdr));
我做到了

 memcpy(eth->h_dest, p->h_source, sizeof(eth->h_source));
但上面的线路导致了SEG故障。我在另一个线程
memcpy((p)->h_-source,received_-packet_-eth->h_-source,sizeof(eth->h_-source))中这样分配
h_-source

h_source
位于struct
struct packets*p
这就是我在其他线程中初始化和分配它的定义
struct packets*p
。因此,
struct packets*p
不是未初始化的指针。我确信当SEGFULT发生时,它会被分配

unsigned char h_source[ETH_ALEN];   /* source ether addr    */
谢谢你的帮助

更新这是函数的完整代码

void get_payload_to_send(struct packets *p, char **pay)
{
    printf("%s --->>> %s", p->ip_source, p->ip_dest);
    int t1;
    *pay = (char *)malloc(sizeof(t1) + 1020 /*1000=payload*/);
    memset(*pay, 0, sizeof(t1) + 1020);
    struct ethhdr *eth = (struct ethhdr *) *pay;
    struct iphdr *ip = (struct iphdr *) (*pay + sizeof(struct ethhdr));
    struct tcphdr *tcp = (struct tcphdr *) (*pay + sizeof(struct ethhdr) + sizeof(struct iphdr));

    //if (p->h_proto == ntohs(p->h_proto) == ETH_P_IP)
    {
        if (p->syn == 1 && p->ack == 0 && p->fin == 0)
        {
            ///Ethernet
            //memcpy(eth->h_dest, p->h_source, sizeof(eth->h_source));

            eth->h_proto = htonl(ETH_P_IP);
            //memcpy(eth->h_source, p->h_dest, sizeof(eth->h_dest));
            ////IP

            // memcpy(ip->saddr, inet_addr(p->ip_dest), sizeof(ip->saddr));
            struct sockaddr_in s1, s2;
            s1.sin_family = AF_INET;
            s1.sin_port = htons(80);
            s1.sin_addr.s_addr = inet_addr(p->ip_source);

            s2.sin_family = AF_INET;
            s2.sin_port = htons(5009);
            s2.sin_addr.s_addr = inet_addr(p->ip_dest);
            //ip->saddr = s1.sin_addr.s_addr;
            sleep(2);
            ip->daddr = s2.sin_addr.s_addr;
            char c[20];
            memcpy(ip->saddr, inet_addr(p->ip_dest), sizeof(c) - 1);
            ip->ihl = 5;
            ip->version = 4;
            ip->tos = 0;
            ip->tot_len = sizeof(t1) + 1020;
            srand(1001);
            ip->id = htonl(rand());
            ip->frag_off = 0;
            ip->ttl = 225;
            ip->protocol = IPPROTO_TCP;
            ip->check = 0;
            tcp->syn = 1;
            tcp->ack = 1;

            memcpy(ip->daddr, inet_addr(p->ip_source), sizeof(c) - 1);

            //ip->check = csum((unsigned short *)*pay, ip->tot_len);
        }
        else if (p->syn == 0 && p->ack == 1)
        {

        }
    }
    //printf("%saddr %s -->>", p->ip_source);
    //printf("daddr %s\n", p->ip_dest);
    //populate eth
}
这是对上述函数进行函数调用的代码

void *task_sender(void *args) {
    struct struct_super_struct *super = (struct struct_super_struct *)args;

    struct packets *p = super->p; //(struct packets *)args;
    printf("Sender\n");
    while (1)
    {
        //printf("got uppder loop SENDER\n");

        pthread_mutex_lock(&mutex);
       
        while (nop == 0)
        {
            pthread_cond_wait(&cond, &mutex);
            //printf("finished waiting in SENDER\n");
        }
        int i = 0;

        printf("NOP is greater than 2 in SENDER %d\n");

        while (nop > 0)
        {
            // check_and_process_connection(super,(p+i));

            //if (p == NULL) break;
            if (strcmp("192.168.10.25", (p+i)->ip_dest) == 0 && (p+i)->syn == 1 && (p+i)->ack == 0)
            {
                //sleep(1);

                //printf("%s\n", (p+i)->ip_dest);
                //if (strcmp((p+i)->ip_dest, "192.168.10.25") == 0)
                {
                    char *pac;
                    struct packets *pt = (p+i);
                    get_payload_to_send((p+i), &pac);
                    struct sockaddr_in temp;
                    struct ethhdr *eth = (struct ethhdr *)pac;
                    struct iphdr *ip = (struct iphdr *)(pac + sizeof(struct ethhdr));
                    struct tcphdr *tcp = (struct tcphdr *)(pac + sizeof(struct ethhdr) + sizeof(struct iphdr));
                    temp.sin_addr.s_addr = ip->saddr;
                    char *source = inet_ntoa(temp.sin_addr);
                    struct sockaddr_in temp1;
                    temp1.sin_addr.s_addr = ip->daddr;
                    char *dest = inet_ntoa(temp1.sin_addr);
                    printf("%s >> %s \n", (p+i)->ip_source, (p+i)->ip_dest);
                    //if (strcmp("192.168.10.25",dest) == 0 && strcmp("192.168.10.25", source) == 0)
                    {
                        ///temp1.sin_addr.s_addr = ip->daddr;
                        printf("should be\n");
                        printf("frm %s to %s syc:%d ack:%d \n",
                               inet_ntoa(temp.sin_addr),
                               inet_ntoa(temp1.sin_addr),
                               tcp->syn, tcp->ack);
                    }
                    /*          
                    printf("__________________________________________________\n");
                    printf("lastop: %d\n", (p+i)->lastop);
                    printf("source: %s %d\n", (p+i)->ip_source, (p+i)->tcp_source);
                    printf("dest: %s %d\n", (p+i)->ip_dest, (p+i)->tcp_dest);
                    printf("syc: %d\n", (p+i)->syn);
                    printf("ack: %d\n", (p+i)->ack);
                    printf("seq: %d\n", (p+i)->seq);
                    printf("ack seq: %d\n", (p+i)->ack_seq);
                    (p+i)->lastop = 0;
                    printf("lastop: %d\n", (p+i)->lastop);
                    */
                }
                //printf("dest port: %d\n", (p+i)->tcp_dest);
            }
            //else { printf("source ip: %s\n", (p+i)->ip_source); printf("dest ip: %s\n", (p+i)->ip_dest); }
            //p++;
            nop--;
            i++;
            //printf("just processed packet SENDER\n");
        }
        //p = NULL;
    
        pthread_mutex_unlock(&mutex);
        nop = 0;
        int s = pthread_cond_signal(&cond);
    }
}
更新2

struct packets {
    int syn;
    char payload[1000];
//    pthread_mutex_t  mutex;
    int lastop;
    unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
    unsigned char h_source[ETH_ALEN];   /* source ether addr    */
    __be16      h_proto;
    char ip_source[20];
    char ip_dest[20];
    int tcp_source;
    int tcp_dest;
    int seq;
    int ack_seq;

    int ack;
    int fin;
    int rst;
    int window;
    int nop;
    struct ethhdr *eth;
    struct iphdr *ip;
    struct tcphdr *tcp;
}; // *p=NULL;

注意我发现使用gdb调试的是
memcpy(eth->h_dest,p->h_source,sizeof(eth->h_source))
eth->hdest
NULL

问题在于您没有提供指向
memset()的正确指针:

char*pay=(char*)malloc(sizeof(t1)+1020);
memset(*支付,0,大小(t1)+1020);
使用动态分配的数组
pay
中的第一个
char
作为目标地址清除内存

正确的形式是

char*pay=malloc(sizeof(t1)+1020);
memset(pay,0,sizeof(t1)+1020);
这是因为
pay
是指向动态分配数组的指针,而
*pay
是指向其第一个元素的值,就像
pay[0]
一样

(在C中,不需要从void*显式转换,例如malloc()的返回值。)


同一错误重复了几次:

struct ethhdr*eth=(struct ethhdr*)*支付;
结构iphdr*ip=(结构iphdr*)(*pay+sizeof(结构ethhdr));
struct tcphdr*tcp=(struct tcphdr*)(*pay+sizeof(struct ethhdr)+sizeof(struct iphdr));
它们声明并初始化指向从动态分配数组
pay
中的第一个字符派生的地址的指针,而不是相对于数组开头的地址

同样,它们的正确形式是

struct ethhdr*eth=(struct ethhdr*)支付;
结构iphdr*ip=(结构iphdr*)(pay+sizeof(结构ethhdr));
struct tcphdr*tcp=(struct tcphdr*)(pay+sizeof(struct ethhdr)+sizeof(struct iphdr));
因为
*pay
指的是
pay
数组中第一个元素的值,而
pay
指的是数组的地址


显然,实际代码是

char**pay;
*pay=malloc(sizeof(t1)+1020);
memset(*支付,0,大小(t1)+1020);
这缺少两个基本的检查:

  • pay
    不为空

  • malloc()
    成功了

  • 该代码可能因上述症状中的任一原因而失败。至少在处,将其改写为

    
    断言(pay!=NULL);
    *pay=malloc(sizeof(t1)+1020);
    断言(*pay!=NULL);
    memset(*支付,0,大小(t1)+1020);
    

    由于
    eth
    ip
    tcp
    变量定义保持其原始形式(即
    *pay
    )。

    问题在于您没有提供指向
    memset()的正确指针。

    char*pay=(char*)malloc(sizeof(t1)+1020);
    memset(*支付,0,大小(t1)+1020);
    
    使用动态分配的数组
    pay
    中的第一个
    char
    作为目标地址清除内存

    正确的形式是

    char*pay=malloc(sizeof(t1)+1020);
    memset(pay,0,sizeof(t1)+1020);
    
    这是因为
    pay
    是指向动态分配数组的指针,而
    *pay
    是指向其第一个元素的值,就像
    pay[0]
    一样

    (在C中,不需要从void*显式转换,例如malloc()的返回值。)


    同一错误重复了几次:

    struct ethhdr*eth=(struct ethhdr*)*支付;
    结构iphdr*ip=(结构iphdr*)(*pay+sizeof(结构ethhdr));
    struct tcphdr*tcp=(struct tcphdr*)(*pay+sizeof(struct ethhdr)+sizeof(struct iphdr));
    
    它们声明并初始化指向从动态分配数组
    pay
    中的第一个字符派生的地址的指针,而不是相对于数组开头的地址

    同样,它们的正确形式是

    struct ethhdr*eth=(struct ethhdr*)支付;
    结构iphdr*ip=(结构iphdr*)(pay+sizeof(结构ethhdr));
    struct tcphdr*tcp=(struct tcphdr*)(pay+sizeof(struct ethhdr)+sizeof(struct iphdr));
    
    因为
    *pay
    指的是
    pay
    数组中第一个元素的值,而
    pay
    指的是数组的地址


    显然,实际代码是

    char**pay;
    *pay=malloc(sizeof(t1)+1020);
    memset(*支付,0,大小(t1)+1020);
    
    这缺少两个基本的检查:

  • pay
    不为空

  • malloc()
    成功了

  • 该代码可能因上述症状中的任一原因而失败。至少在处,将其改写为

    
    断言(pay!=NULL);
    *pay=malloc(sizeof(t1)+1020);
    断言(*pay!=NULL);
    memset(*支付,0,大小(t1)+1020);
    

    由于
    eth
    ip
    tcp
    变量定义保持其原始形式(即
    *pay
    )。

    这些行上有两个主要错误:

    struct ethhdr *eth = (struct ethhdr *) *pay;
    struct iphdr *ip = (struct iphdr *) (*pay + sizeof(struct ethhdr));
    struct tcphdr *tcp = (struct tcphdr *) (*pay + sizeof(struct ethhdr) + sizeof(struct iphdr));
    
    • pay*
      指向的内存是使用一个神奇的数字分配的,
      ethhdr
      iphdr
      tcphdr
      的大小可能是相同的,但我不想继续工作
          void get_payload_to_send(struct packets *p,char **pay)
          {
              printf("%s --->>> %s",p->ip_source,p->ip_dest);
              int t1;
              *pay=(char *) malloc(sizeof(t1)+1020/*1000=payload*/);
              memset (*pay, 0, sizeof(t1)+1020);
              struct ethhdr *eth = (struct ethhdr *) *pay;
              struct iphdr *ip = (struct iphdr *) (*pay + sizeof(struct ethhdr));
              struct tcphdr *tcp = (struct tcphdr *) (*pay + sizeof(struct ethhdr) + sizeof(struct iphdr));
      
      memcpy(eth->h_dest,p->h_source,sizeof(eth->h_source));