c++ - STL map.find 在使用 vs2010 的调试和发布中表现不同

标签 c++ dictionary stl

我正在使用 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 作为 map 中的关键元素。

map 是 map< FiveTuple, Flow, FlowCmp>,其中 FlowCmp 是一个使用 memcmp 来查看 FiveTuple a 是否小于 FiveTuple b 的结构,就像 operator<。 为了查找数据包的流是否存在,我编写了如下代码,其中 m 是映射的名称,five_tuple 是从数据包中提取信息的 FiveTuple:

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。而且我发现没有初始化问题。如何解决发布版本问题?

最佳答案

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

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

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

关于c++ - STL map.find 在使用 vs2010 的调试和发布中表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12968545/

相关文章:

c++ - C++中的慢动作

c++ - 如何转换枚举?

python - 如何基于相同类型的现有字典并使用原始名称在适当的位置构建新的 defaultdict(list)

c++ - stringstream 可以解析这样的东西吗?

c++ - 为什么 C++ 允许将指向基对象的指针转换为派生类的指针

c++ - map 迭代器不可取消引用

python - 将python字典转换为大写

python - 将两个字典的信息翻译成字典列表

c++ - std::function 和类继承

c++ - 就地 C++ 设置交集