在Socket UDP上使用Getaddrinfo()和SendTo()失败 - 分段错误(核心转储)

时间:2013-03-28 20:07:27

标签: sockets struct udp sendto getaddrinfo

在我开始使用getaddrinfo()来检索动态IP地址后,我的套接字的sendTo()不再起作用并返回错误“Segmentation fault(core dumped)”。为什么会发生这种情况,请问我的代码中是否缺少任何初始化或内存分配?我已经尝试了一段时间,但还没弄清楚原因。任何帮助都会非常感激!

以下是代码部分:

    // variables declaration
    int s;
    struct sockaddr_in si_other;
    struct addrinfo hints;     
    struct addrinfo *result, *rp;
    char *hostname = "localhost"; 
    const char* portnum = "8000"; 

    // settings of hints
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
    hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
    hints.ai_flags = 0;
    hints.ai_protocol = 0;
    hints.ai_flags = AI_NUMERICSERV;

    // resolve dynamically IP adress by getaddrinfo()
    s = getaddrinfo(hostname, NULL, &hints, &result); 
    if (s != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);
    }
    // create socket s
    for (rp = result; rp != NULL; rp = rp->ai_next) 
    {
            s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
    }

    // loop for sending m x struct ECA_message_t 
    int m=0;
for (; m<NbMesPerFile; ++m) 
    {

            ECA_message_t* ECA_paquet;
            ECA_paquet=(ECA_message_t*)malloc(sizeof(ECA_message_t)*2400); 
            // 2400 to workaround some not understood memory issue and make sendto() to 
            // work  

            // function initializing ECA_paquet
            Client_update_ECA_data(ECA_paquet,m);
            if (sendto(s, ECA_paquet, sizeof(ECA_paquet)*2400, 0 ,(struct 
                  sockaddr*)&si_other,slen)==-1)
    {
        perror("sendto()");
    }
    }

要向我的结构添加详细信息,并找到我的malloc(sizeof(ECA_message_t)出错的原因,请参阅下面的结构ECA_message_t的代码:

typedef struct{

unsigned int version:2;
unsigned int p:1;
unsigned int x:1;
unsigned int cc:4;
unsigned int m:1;
unsigned int pt:7;
unsigned int seq:16;
u_int32_t timestamp;
u_int32_t ssrc;
u_int32_t csrc;
} RTP_header_t;             // 16 bytes


typedef struct {

unsigned int version:2;
unsigned int reserved_1:6;
unsigned int reserved_2:8;
unsigned int number_sample:16;

}ECA_header_t;              // 4 bytes

typedef struct {

//every line composed of 6 values, 2 byte per value, all signed
int32_t v_phase_1;
int32_t v_phase_2;
int32_t v_phase_3;
int32_t i_phase_1;
int32_t i_phase_2;
int32_t i_phase_3;

}ECA_payload_t;             // 12 bytes

typedef struct {

RTP_header_t rtp_header;
ECA_header_t eca_header;
ECA_payload_t eca_payload[MAX_ECA_SAMPLES]; // MAX_ECA_SAMPLES of 100

}ECA_message_t;             // 1220 bytes

这是Aborted(Core dumpted)Back trace消息:

*** glibc detected *** ./clientUDPIniDyn: double free or corruption (!prev): 0x081768c8 ***
 ======= Backtrace: =========
 /lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb7642ee2]
 ./clientUDPIniDyn[0x804896b]
 /lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75e64d3]
 ./clientUDPIniDyn[0x80486b1]
 ======= Memory map: ========
 08048000-0804a000 r-xp 00000000 08:01 1319522    /home/lin/ULB/Memoire/Client_Server
 /Server/clientUDPIniDyn
 0804a000-0804b000 r--p 00001000 08:01 1319522    /home/lin/ULB/Memoire/Client_Server
 /Server/clientUDPIniDyn
 0804b000-0804c000 rw-p 00002000 08:01 1319522    /home/lin/ULB/Memoire/Client_Server
 /Server/clientUDPIniDyn
 08176000-08197000 rw-p 00000000 00:00 0          [heap]
 b7589000-b75a5000 r-xp 00000000 08:05 264147     /lib/i386-linux-gnu/libgcc_s.so.1
 b75a5000-b75a6000 r--p 0001b000 08:05 264147     /lib/i386-linux-gnu/libgcc_s.so.1
 b75a6000-b75a7000 rw-p 0001c000 08:05 264147     /lib/i386-linux-gnu/libgcc_s.so.1
 b75bf000-b75ca000 r-xp 00000000 08:05 293796     /lib/i386-linux-gnu/libnss_files-
 2.15.so
 b75ca000-b75cb000 r--p 0000a000 08:05 293796     /lib/i386-linux-gnu/libnss_files-
 2.15.so
 b75cb000-b75cc000 rw-p 0000b000 08:05 293796     /lib/i386-linux-gnu/libnss_files-
 2.15.so
 b75cc000-b75cd000 rw-p 00000000 00:00 0 
 b75cd000-b7770000 r-xp 00000000 08:05 293791     /lib/i386-linux-gnu/libc-2.15.so
 b7770000-b7771000 ---p 001a3000 08:05 293791     /lib/i386-linux-gnu/libc-2.15.so
 b7771000-b7773000 r--p 001a3000 08:05 293791     /lib/i386-linux-gnu/libc-2.15.so
 b7773000-b7774000 rw-p 001a5000 08:05 293791     /lib/i386-linux-gnu/libc-2.15.so
 b7774000-b7777000 rw-p 00000000 00:00 0 
 b778d000-b7791000 rw-p 00000000 00:00 0 
 b7791000-b7792000 r-xp 00000000 00:00 0          [vdso]
 b7792000-b77b2000 r-xp 00000000 08:05 293804     /lib/i386-linux-gnu/ld-2.15.so
 b77b2000-b77b3000 r--p 0001f000 08:05 293804     /lib/i386-linux-gnu/ld-2.15.so
 b77b3000-b77b4000 rw-p 00020000 08:05 293804     /lib/i386-linux-gnu/ld-2.15.so
 bfbad000-bfbce000 rw-p 00000000 00:00 0          [stack]
 Aborted (core dumped)

2 个答案:

答案 0 :(得分:0)

// create socket s
for (rp = result; rp != NULL; rp = rp->ai_next) 
{
        s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
}

你在这里泄漏文件描述符(套接字)。循环的每次迭代s都会被重新分配。 s的先前值丢失了。 (我不知道你的链表有多长)

// loop for sending m x struct ECA_message_t 
int m=0;
for (; m<NbMesPerFile; ++m) 
    {

            ECA_message_t* ECA_paquet;
            ECA_paquet=(ECA_message_t*)malloc(sizeof(ECA_message_t)*2400); 
            // 2400 to workaround some not understood memory issue and make sendto() to 
            // work  

            // function initializing ECA_paquet
            Client_update_ECA_data(ECA_paquet,m);
            if (sendto(s, ECA_paquet, sizeof(ECA_paquet)*2400, 0 ,(struct 
                  sockaddr*)&si_other,slen)==-1)
    {
        perror("sendto()");
    }
}

你在这里泄漏记忆。循环的每次迭代ECA_paquet都会被重新分配。并且以前的ECA_paquet值丢失了。永远。 (我不知道NbMesPerFile有多大)

(这可能不是你的段错误的原因,但它至少表明质量不合格)你还应不强制转换malloc()的返回值,(+ #include <stdlib.h>, ,再检查malloc()的返回值。然后调高编译器的警告级别。

答案 1 :(得分:0)

以下是固定代码,使用calloc()

不再出现分段错误
for (rp = result; rp != NULL; rp = rp->ai_next) 
{
     s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); // socket creation

     ECA_message_t* ECA_paquet;
     ECA_paquet=calloc(NbMesPerFile, sizeof(* ECA_paquet)); // calloc to assign table [NbMesPerFile] length bloc memory for my struct EA_message_t

     // sending m paquets of my struct 
     int m=0;
     for (; m<NbMesPerFile; ++m) 
     {

         Client_update_ECA_data(ECA_paquet,m);  //update the ECA data paquet

         if (sendto(s,ECA_paquet, sizeof(*ECA_paquet) ,0, rp->ai_addr,rp->ai_addrlen)==-1) // send data ECA data pointed by ECA_paquet
         {
             perror("sendto()");
         }
     }

}