mardi 1 novembre 2016

std string assignment causes double free curruption

I am using pf_ring zc for packet sniffing. with the following peace of code, i can packet capture network packets and save them as std string.

//Global         
struct _Session_flag {
     uint_64t Number;
}
std::string* _Session_buffer= new std::string[_Max_Element_Session_buffer];
==============================================================

   long int c = 0, i = 0;        
        // all _Session_buffer[i] reserved with size 300
        for (;;) {
            if (likely(pfring_zc_recv_pkt(zqs, &buffer_session, _wait_for_packet) >= 0)) {
                u_char *pkt_data = pfring_zc_pkt_buff_data(buffer_session, zqs);
                try{
                _Session_buffer[c] = std::string (pkt_data + _SessionHeaderSize, pkt_data + _snapLengthSession);;
                }catch(...){
                    // AFAIR never happened
                     LOG_INFO("Not Captured. Packet= %s",payload.c_str() );                
                    continue;
                }                
                _Session_flag->_Number++;
                c = (c+ 1)% _Max_Element_Session_buffer;                                
            }
        }

everything is OK. But trying to read Packets from _Session_buffer[x] causes double free or corruption (out) as gdb say:

*** Error in `/home/../Project/ng4-m2-cb/ng4-m2-cb': double free or corruption (out): 0x00007fff88001af0 ***

Program received signal SIGABRT, Aborted. [Switching to Thread
0x7ffff1bdb700 (LWP 8642)] 0x00007ffff67ebc37 in __GI_raise
(sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56  ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
    .
    .
    .
    .

this peace of code is run by multiple threads. each thread has a unique ID as MyID. Each thread reads packets from an offset of _Session_buffer[]. i am sure all threads have their own scope of work and there is no conflict on accessing _Session_buffer.

        short MyID = giveMyID();
        LOG_INFO("Session Worker :%d started", MyID);       
        uint64_t p_counter=0;
        std::string packet;           packet.reserve(300+2);        
        long int l = 0, index;
        index=MyID;  
        for (;;) {                                       
            if (p_counter >= (_Session_flag->_Number - MyID)) {                
             boost::this_thread::sleep(boost::posix_time::milliseconds(_SessionThreadSleepTime));
                continue;
            }
            // making _Session_buffer as Circular Buffer;         
            if(index>=_Max_Element_Session_buffer){
                index=MyID;                            
            }
            try {
                 //as gdb said, this line gives Double free corruption
                 packet= _Session_buffer[index];
                 // i tried this one but no success achieved
                 //packet= _Session_buffer[index].c_str();
            } catch (...) {
                index += _SessionThreadCount;     
                p_counter += _SessionThreadCount;
                continue;
            }          
            index += _SessionThreadCount;        
            p_counter += _SessionThreadCount;
         }

The question is clear!!. Why double free corruption happened? pf_ring zc does not capture packet as NULL pointer. Saving packets works well but Reading them has Problem. On What situations std string assignment returns Error?

Thanks.

Aucun commentaire:

Enregistrer un commentaire