【问题标题】:stl map.find perform differently in debug and release using vs2010stl map.find 在使用 vs2010 的调试和发布中表现不同
【发布时间】:2012-10-19 06:28:14
【问题描述】:

我正在使用 stl map 来存储从 pcap 文件中提取的流信息。当数据包到来时,我使用 map.find 来查找数据包所属的流是否存在。我必须使用 map.find 两次,因为从 A 到 B 的数据包和从 B 到 A 的数据包属于同一流。

struct FiveTuple
{
unsigned short source_port;
unsigned short dest_port;
unsigned int source_ip_addr;
unsigned int dest_ip_addr;
unsigned char transport_proto_type;
};

FiveTuple 标识一个流。我使用 FiveTuple 作为 map 中的关键元素。

map 是 map,其中 FlowCmp 是一个结构体,使用 memcmp 来查看 FiveTuple a 是否小于 FiveTuple b,就像 operator

auto it = m.find(five_tuple);
if( it == m.end())
{
     //swap source and dest ip/port in five_tuple,
    it = m.find(five_tuple);

    if(it == m.end())
    {
          //do something
    }
}

在vs2010的debug版本中,结果是合理的。当我将其更改为发布版本时,我发现第二个 m.find 大部分时间都没有返回正确的迭代器,而是给了我 m.end。而且我发现没有初始化问题。发布版本问题如何解决?

【问题讨论】:

  • 尝试将operator< 添加到您的元组结构中。只是猜测。
  • @Naveen:没用,因为他将明确的比较器传递给 map。
  • @Yihong Xiang:Debug 构建将对象/内置/等的内存初始化为0 是典型的(也是愚蠢的......),这保证了稳定性。但是在 Release 中,这种“有用”的 0-ing 被删除了,因为它通常是不必要的......

标签: c++ dictionary stl


【解决方案1】:

似乎您正在对 FiveTuple 对象执行 memcmp() 。这是未定义的行为,因为 FiveTuple 包含尾随垃圾字节。这些尾随垃圾字节在调试版本和发布版本中是不同的,因此您会得到不同的结果。您应该重写 FlowCmp,使其不使用 memcmp()。

这是基于提供的有限信息的猜测,但如果您想测试一下,请尝试cout << sizeof(FiveTuple);。我打赌你会看到sizeof(FiveTuple) > sizeof(short) + sizeof(short) + sizeof(int) + sizeof(int) + sizeof(char)。换句话说,你的结构中有垃圾,你不应该使用 memcmp。

当然 memcmp 不好还有另一个原因,因为这意味着您的代码将不可移植,因为它的行为将取决于您平台的 endianess。这本身就是不将 memcmp 用于此目的的充分理由。

【讨论】:

  • 有了你的答案,我使用memset将five_tuple初始化为0,现在结果似乎是正确的,谢谢。
  • 好的,很高兴为您提供帮助。但是反对 memcmp 的论点仍然成立。它是非便携式的。
  • 嗯,字节序不是问题,因为我在使用 map.find 之前已经将 ip 地址和端口转换为本地字节序。再次感谢。
  • @john:我猜这里的顺序并不重要,事实上,哈希函数也可以。
  • @YihongXiang 在这里使用memcmp 有真正的理由吗?这根本不是一个好主意,当然也没有必要。
猜你喜欢
  • 1970-01-01
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-24
  • 1970-01-01
  • 1970-01-01
  • 2017-05-28
相关资源
最近更新 更多