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



我通过复制到初始化的指针来获得segFault。这是相关的代码

*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));

但这条线正在引发一场断层。我在其他线程memcpy((p)->h_source, received_packet_eth->h_source, sizeof(eth->h_source));中像这样分配h_source

h_source在结构体struct packets *p内这就是我在其他线程中初始化和分配其定义struct packets *p的方式,请参阅上文。所以struct packets *p不是一个未初始化的指针。我确信它是在segFault发生时分配的。

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 %sn", 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("Sendern");
while (1)
{
//printf("got uppder loop SENDERn");
pthread_mutex_lock(&mutex);

while (nop == 0)
{
pthread_cond_wait(&cond, &mutex);
//printf("finished waiting in SENDERn");
}
int i = 0;
printf("NOP is greater than 2 in SENDER %dn");
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("%sn", (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 ben");
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: %dn", (p+i)->lastop);
printf("source: %s %dn", (p+i)->ip_source, (p+i)->tcp_source);
printf("dest: %s %dn", (p+i)->ip_dest, (p+i)->tcp_dest);
printf("syc: %dn", (p+i)->syn);
printf("ack: %dn", (p+i)->ack);
printf("seq: %dn", (p+i)->seq);
printf("ack seq: %dn", (p+i)->ack_seq);
(p+i)->lastop = 0;
printf("lastop: %dn", (p+i)->lastop);
*/
}
//printf("dest port: %dn", (p+i)->tcp_dest);
}
//else { printf("source ip: %sn", (p+i)->ip_source); printf("dest ip: %sn", (p+i)->ip_dest); }
//p++;
nop--;
i++;
//printf("just processed packet SENDERn");
}
//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->hdestNULL

您报告在给定此设置的情况下。。。

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()抛出了一个segfault:

memcpy(eth->h_dest,p->h_source,sizeof(eth->h_source));

,gdb向您透露eth->h_dest在调用时为null。

好吧,目标指针为null完全解释了segfault。如果eth->h_dest是一个指针,并且所有零位都是其类型的空指针表示,那么当然它是空的。您使用memset()调用将其设置为所有零位。

在将数据复制到eth->h_dest之前,您需要为其分配足够的(额外的(空间,或者使用指针分配将其指向现有对象。背景还不够清楚,我无法判断其中哪一个更合适。

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

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*指向的内存是使用幻数分配的,ethhdriphdrtcphdr的大小可能相同,但我不想处理该代码,访问可能会越界。

  • 关于对准,可能会发生ethhdr必须降落在X的倍数上,但pay不是。这将触发一个错误(malloc将返回一个对齐度至少为max_align_t的地址,但所有事情都可能发生额外的添加(。

问题是您没有为memset():提供正确的指针

char *pay=(char *) malloc(sizeof(t1)+1020);
memset (*pay, 0, sizeof(t1)+1020);

使用动态分配阵列CCD_ 24中的第一个CCD_。

正确的形式是

char *pay = malloc(sizeof(t1)+1020);
memset (pay, 0, sizeof(t1)+1020);

这是因为pay是指动态分配的数组的指针,而*pay指的是其第一个元素的值,就像pay[0]一样。

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


相同的错误重复多次:

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中的第一个字符派生的地址,而不是相对于数组开头的地址。

同样,它们的正确形式是

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是指pay数组中第一个元素的值,而pay是指数组的地址。


显然,实际代码是

char **pay;
*pay = malloc(sizeof (t1) + 1020);
memset (*pay, 0, sizeof (t1) + 1020);

这缺少两项基本检查:

  1. pay不是空

  2. malloc()接替

代码可能因任何一种原因而失败,并出现所述症状。在最小时,将其重写为


assert(pay != NULL);
*pay = malloc(sizeof (t1) + 1020);
assert(*pay != NULL);
memset(*pay, 0, sizeof (t1) + 1020);

ethiptcp变量定义保持其原始形式(即*pay(。

最新更新