首页
社区
课程
招聘
回调函数与多线程导致内存错误
发表于: 2012-6-4 12:28 5422

回调函数与多线程导致内存错误

2012-6-4 12:28
5422
程序在没有加入全局缓冲队列和多线程操作时,程序运行稳定。加入全局缓冲队列和多线程操作后,也添加了互斥体防止子线程和主线程同时对全局队列进行读写操作。
新版本在2003 ServerR2运行正常
但是在XP中却运行一段时间后就会报错。"0x0040c00d"指令引用的“0x00000010”内存。该内存不能为read。

下面是较之前稳定版  新加有关队列和线程的代码。之前稳定版本对数据包的操作都在回调函数里面完成。现在是回调函数把数据包信息保存在全局队列里,子线程不断从全局队列中取出数据包信息进行分析。

希望知道问题出在哪里?如何解决?
(如果我给出的信息不够,请说明,我会尽量补全)

#difine ETH_ALEN 6

#include <queue>

std::queue<pd> currentdata;
Thread_h th_caphand;
extern bool ifrun;
u_int8_t suscount = 0;
HANDLE hmutex;

typedef struct
{
        struct EtherHeader eh;
        struct IpHeader iph;
} Packet_Hdr;

typedef struct
{
        time_t ltime;
        u_int16_t tot_len;
        u_int32_t saddr;
        u_int32_t daddr;
        u_int8_t ether_shost[ETH_ALEN];
        u_int8_t ether_dhost[ETH_ALEN];
}pd;

//类的申明
class LabTrafficSniffer
{
public:
        LabTrafficSniffer( LabTrafficMeter *meter );
        bool PrepareSniff( const char *adapter, const IpFilter filter[], int num, bool filter_dns,
                u_int32_t &ip, char err[ERRBUF_SIZE] );
        bool Sniff(void);
        void BreakSniff(void);
        ~LabTrafficSniffer();

private:
        LabTrafficSniffer(void);
        //内容处理器
    static void cap_handler( LabTrafficSniffer* ts, const struct pcap_pkthdr* pkt_header, const Packet_Hdr* pkt_data );
        static CALL_BACK cap_hand_routine(LabTrafficSniffer* ts);

        LabTrafficMeter *meter_;
        pcap_t *caphandle_;

        u_int8_t ether_[ETH_ALEN];
        u_int32_t subnet_ip_;
        u_int32_t subnet_mask_;
};

//包含回调函数的成员函数
bool LabTrafficSniffer::Sniff(void)
{
        bool succ = true;

        if( caphandle_ == NULL ) return false;
        hmutex = CreateMutex( NULL, TRUE, NULL );//创建互斥体
        ReleaseMutex( hmutex );//释放互斥体
        th_caphand = CreateThread( NULL, 0, reinterpret_cast<ThreadRoutine>(cap_hand_routine), this, 0, NULL );
        // WinPcap在这循环抓包
        switch( pcap_loop( caphandle_, -1, reinterpret_cast<pcap_handler>(cap_handler), reinterpret_cast<u_char*>(this) ) )
                {
                case -1:
                        {// error
                        succ = false;
                        }break;

                case -2:
                        {// pcap_breakloop called
                        }break;

                default:break;
                }//end switch

        pcap_close( caphandle_ );
        caphandle_ = NULL;

        return succ;
}

//回调函数
void LabTrafficSniffer::cap_handler( LabTrafficSniffer* thissnif, const struct pcap_pkthdr* pkt_header, const Packet_Hdr* pkt_data )
{
        pd tempd;
        //取出需要的数据包信息
        tempd.ltime = pkt_header->ts.tv_sec;
        tempd.tot_len = pkt_data->iph.tot_len;
        tempd.daddr = pkt_data->iph.daddr;
        tempd.saddr = pkt_data->iph.saddr;
        memcpy(tempd.ether_dhost, pkt_data->eh.ether_dhost, 6*sizeof(u_int8_t));
        memcpy(tempd.ether_shost, pkt_data->eh.ether_shost, 6*sizeof(u_int8_t));
        WaitForSingleObject( hmutex, INFINITE );//等待互斥体
        //将数据包信息压入缓冲队列队尾
        currentdata.push(tempd);
        ReleaseMutex( hmutex );//释放互斥体
        if (1 == suscount) //若线程被挂起状态,则恢复线程
        {
                suscount--;
                ResumeThread(th_caphand);
        }
}

//子线程函数
CALL_BACK LabTrafficSniffer::cap_hand_routine(LabTrafficSniffer* ts)
{
        while (ifrun)
        {
                if (!currentdata.empty())
                {
                        pd tempad;
                        tempad = currentdata.front();
                        WaitForSingleObject( hmutex, INFINITE );//等待互斥体
                        currentdata.pop();
                        ReleaseMutex( hmutex );//释放互斥体
                        u_int32_t pkt_len = ntohs( tempad.tot_len );
                        if( (tempad.daddr & ts->subnet_mask_) == ts->subnet_ip_ )
                        {// 数据包是下载。Count是meter_对象的成员函数
                                ts->meter_->Count( tempad.ether_dhost, tempad.daddr, pkt_len, true, tempad.ltime );
                        }
                        else if( (tempad.saddr & ts->subnet_mask_) == ts->subnet_ip_ )
                        {// 数据包是上传。Count是meter_对象的成员函数
                                ts->meter_->Count( tempad.ether_shost, tempad.saddr, pkt_len, false, tempad.ltime );
                        }
                }
                else
                {
                        suscount++;
                        SuspendThread(th_caphand);
                }
        }
        return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 193
活跃值: (64)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
tempad = currentdata.front();
      WaitForSingleObject( hmutex, INFINITE );//等待互斥体
      currentdata.pop();
      ReleaseMutex( hmutex );//释放互斥体
没有判断currentdata 是否为空
2012-6-4 13:27
0
雪    币: 278
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
  if (!currentdata.empty())
    {
      pd tempad;
      tempad = currentdata.front();
      WaitForSingleObject( hmutex, INFINITE );//等待互斥体
      currentdata.pop();
      ReleaseMutex( hmutex );//释放互斥体

判断了。大条件就是判断队列是否为空,运行的过程中还是会出现内存报错问题
2012-6-4 13:50
0
雪    币: 193
活跃值: (64)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
判断空的时候没锁
2012-6-9 12:59
0
游客
登录 | 注册 方可回帖
返回
//