C++二級指針與引用

先來看一段代碼,功能是實現IP的統計,如果一個IP出現三次就觸發相應的處理,但是每個Ip統計始終爲1,具體如下,

EdgeMonitor.h

#include <unistd.h>
#include <stdarg.h>
#include <iostream>
#include <string>
#include <map>

using namespace std;

#define EDGE_DEBUG
#ifdef EDGE_DEBUG
#define DBG_LOG(...) do {fprintf(stderr, "File: %s Line %d - ", __FILE__, __LINE__);\
                            fprintf(stderr, __VA_ARGS__);\
                            fprintf(stderr, "\n");}\
                            while(0)
#else
#define DBG_LOG(...)
#endif

static const int g_edge_connect_nr = 3;
enum {MAIL_WARN_TYPE_EDGE_SMTP = 32};

class CEdgeRecord
{
    public:
        CEdgeRecord();
        ~CEdgeRecord();
        int checkNr(string &clientIP);
    private:
        int m_nr;
};

class CEdgeMonitor
{
public:
    CEdgeMonitor();
    ~CEdgeMonitor();
    int addOrUpdateRecord(string &clientIP, CEdgeRecord &r_outdata);
    int process(string &clientIP);
    
private:
    map<string, CEdgeRecord*> m_all_ipmap;//維護所有ip的當前以及歷史ip信息
};

#endif


EdgeMonitor.cpp

#include "EdgeMonitor.h"

CEdgeRecord::CEdgeRecord ()
{
   m_nr = 0;
}

CEdgeRecord::~CEdgeRecord ()
{}

int CEdgeRecord::checkNr(string &clientIP)
{
    int warntype = 0;
    m_nr++;
    if(m_nr >= g_edge_connect_nr)
    {
        warntype = MAIL_WARN_TYPE_EDGE_SMTP;
        m_nr = 0;
    }
    DBG_LOG("MAIL_EDGE_WARN: clientIP(%s), nr(%d), NR(%d)", 
                  clientIP.c_str(), m_nr, g_edge_connect_nr);
    return warntype;
}


CEdgeMonitor::CEdgeMonitor()
{
  
}

CEdgeMonitor::~CEdgeMonitor()
{
     map<string, CEdgeRecord*>::iterator	 iter_rbtree_map;
    
    iter_rbtree_map = m_all_ipmap.begin();
    while (iter_rbtree_map != m_all_ipmap.end())
    {
        if (NULL != iter_rbtree_map->second)
        {
            delete iter_rbtree_map->second;
            iter_rbtree_map->second = NULL;
        }
        iter_rbtree_map++;
        
    }
    m_all_ipmap.clear();
}
int CEdgeMonitor::addOrUpdateRecord(string &clientIP, CEdgeRecord &r_outdata)
{
    CEdgeRecord *p_record = NULL;
    if (m_all_ipmap.count(clientIP) < 1)
    {
        p_record = new CEdgeRecord();
        if (NULL == p_record)
        {
            DBG_LOG("Failed to new CEdgeRecord");
            return -1;
        }
       
        m_all_ipmap.insert(make_pair(clientIP, p_record));
    }
    else
    {
        p_record = m_all_ipmap[clientIP];  

    }
    r_outdata = *p_record;
  
    return 0;
}

int CEdgeMonitor::process(string &clientIP)
{
    CEdgeRecord r_outdata;
    int warnType = 0;
   
    //添加到歷史記錄中
    if(0 != addOrUpdateRecord(clientIP, r_outdata))
    {
        return -1;
    }
    
    //檢查告警
    warnType =r_outdata.checkNr(clientIP);
    DBG_LOG("warnType (%d)", warnType);

    return 0;
}
int main()
{
    string clientip("172.22.1.16");
    string clientip2("172.22.1.17");
    string clientip3("172.22.1.18");
    CEdgeMonitor *mm = new CEdgeMonitor();
    mm->process(clientip);
    mm->process(clientip);
    mm->process(clientip);
    mm->process(clientip);
	
    mm->process(clientip2);
    mm->process(clientip2);
    mm->process(clientip2);
    mm->process(clientip2);

    delete mm;

    return 0;
}



# g++ EdgeMonitor.cpp
#./a.out

File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17),nr(1),NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)

原因在於

r_outdata = *p_record;

上述語句的意思是調用複製操作符,p_record的內容複製到r_outdata的空間,而在proccess中調用checkNr()函數的操作實際上是在p_record的副本空間運行,所以m_nr的值始終爲1。

解決辦法:

int CEdgeMonitor::addOrUpdateRecord(string &clientIP, CEdgeRecord **pp_outdata)
{
。。。。。
 *pp_outdata = p_record;
}
int CEdgeMonitor::process(string &clientIP)
{
   CEdgeRecord *p_outdata = NULL;

   int  ret = addOrUpdateRecord(clientIP, &p_outdata)

 if(0 != ret || NULL ==p_outdata )
    {
        return -1;
    }
  warnType = p_outdata->checkNr(clientIP);
。。。。
}
# g++ EdgeMonitor.cpp
#./a.out

File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(2), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(0), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (32)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.16), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17), nr(2), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17), nr(0), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (32)
File: EdgeMonitor.cpp Line 23 - MAIL_EDGE_WARN: clientIP(172.22.1.17), nr(1), NR(3)
File: EdgeMonitor.cpp Line 88 - warnType (0)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章