2013-11-12 3 views
1

Я использовал unorder_map в своей программе. проблема в том, что не может найти ключ, который я вставленной в карте иногда, я не знаю причину, следующий мой код:unordered_map не может найти ключ

class FlowKey: public std::pair<const char*, unsigned int> 
{ 
public: 
    FlowKey(const char* s, unsigned int l): std::pair<const char*, unsigned int>(s, l) { 
      fprintf(stderr, "raw string %s len %u, after pair, first %s second %u", s, l, this-  >first, this->second); 
    } 
    bool operator==(const FlowKey& c) const 
    { 
      if (this->second == c.second) { 
        if (0 == strncmp((char*)this->first, (char*)c.first, this->second)) { 
          fprintf(stderr, "key compare true\n"); 
          return true; 
        } else { 
          fprintf(stderr, "this first ip:%s c first ip:%s\n", (char*)this->first, (char*)c.first); 
        } 
      } else { 
        fprintf(stderr, "this second %d, c second %d\n", this->second, c.second); 
      } 
      fprintf(stderr, "key compare false\n"); 
      return false; 
    } 
}; 

class FlowKeyHash 
{ 
public: 
    size_t operator()(const FlowKey& that) const 
    { 
      unsigned int h = fnv_32a_buf(that.first, that.second, FNV_32A_INIT); 
      fprintf(stderr, "ip %s len %u digest %u\n", that.first, that.second, h); 
      return (size_t) h; 
    } 
}; 
typedef std::unordered_map<unsigned int, TcpInfo*, EmptyHash> UserAgent_Map; 
typedef std::unordered_map<FlowKey, UserAgent_Map, FlowKeyHash> IP_Map; 

использование:

FlowKey k(ipString, strlen(ipString)); 
IP_Map::iterator it = m_iptable.find(k); 
if (it == m_iptable.end()) { 
      //insert new entry to ip table and useragent table 
      struct timeval time; 
      gettimeofday(&time, NULL); 
      fprintf(stderr, "ip not equel, insert: ip:(%s)ip-digest(%u), k first:%s k second %d tablesize %d hashsize %lu\n", ipString, ip_digest, k.first, k.second, m_tableSize, m_iptable.size()); 
      for(it = m_iptable.begin(); it != m_iptable.end(); ++it) { 
        fprintf(stderr, "key %s len %d\n", it->first.first, it->first.second); 
      } 
      ++m_tableSize; 
    } else { 
      //update ip table 
      struct timeval time; 
      gettimeofday(&time, NULL); 
      UserAgent_Map::iterator it2 = it->second.find(user_agent_digest); 
      if (it2 == it->second.end()) { 
        //insert new entry to user_agent table 
        ++m_tableSize; 
        fprintf(stderr, "user-agent not equel, insert: use-agent-digest(%u)\n", user_agent_digest); 
      } 

программа вставили пару ключей (192.168.2.20, 12), то можно найти этот ключ где-то, но иногда не может найти этот ключ, отображение журнала:

raw key 192.168.2.20 len 12, after pair, first 192.168.2.20 second 12 
ip 192.168.2.20 len 12 digest 1737338608 
this first ip:192.168.2.20 c first ip:184.28.16.107 
key compare false 
ip 192.168.2.20 len 12 digest 1737338608 
this first ip:192.168.2.20 c first ip:184.28.16.107 
key compare false 
ip not equel, insert: ip:(192.168.2.20)ip-digest(1737338608), k first:192.168.2.20 k second 12 tablesize 1 hashsize 2 
key 192.168.2.20 len 12 
key 184.28.16.107 len 12 

это так странно, ключ для искать - < 192.168.2.20, 12>, и он был на карте, почему функция find не может ее найти, почему поиск ключа был изменен на 184.28.16.107 во время вызова find(). до и после find() ключ находится в 192.168.2.20, во время находок он равен 184.28.16.107, а len 12 не прав, почему и где находится ключ < 184.28.16.107,12> от любого может найти мое использование unordered_map не так? или логическая ошибка программы, для этого стоит много времени, но я не могу найти никакой причины. можешь мне помочь?

+1

Итак, что случилось с исходным указателем 'char *', который обращается к начальной вставке? Или это его жизнь не то, что вы считаете важным (обратите внимание: это * важно *). Вы ищете то, что ожидаете найти, поэтому вы должны добавить его раньше (и удобно опустить этот код со своего поста, подавляя любые надежды на воспроизводимость на нашем конце). Что случилось с этим указателем (и содержимым, на которое он указывает) между * этим * вставкой и * этим * поиском? – WhozCraig

+0

WhozCraig, я добавил несколько записей в мою программу, посмотрю мое новое редактирование, ключ <192.168.2.20, 12> действительно был вставлен на карту. но во время поиска() поиск ключа изменился с 192.168.2.20 до 184.28.16.107, я не знаю, почему –

+1

его, потому что указатель, который вы добавляете, используется для повторного использования буфера или, что еще хуже, его в области видимости который позже оставлен, что приводит к оборванному указателю. Я * сильно * предлагаю вам использовать 'std :: pair ' и изменить вашу хеш-функцию для использования 'this.first.c_str()' для первого параметра вычисления хэша. – WhozCraig

ответ

0

Похоже, что проблема с висячим указателем, как анализируемый WhozCraig. Вы можете использовать один и тот же ipString дважды или три ...

Можете ли вы изменить «const char *» в вашей паре для строки? Бьюсь об заклад, это решит вашу проблему.

+0

да, вы правы, char * просто копия значения, не копируйте всю строку символов, изменение в строку все в порядке, спасибо вам большое. –

Смежные вопросы