stl map.find使用vs2010在调试和发布中执行不同的操作

Yih*_*ang 4 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;
};
Run Code Online (Sandbox Code Playgroud)

FiveTuple识别流程.我使用FiveTuple作为地图中的关键元素.

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
    }
}
Run Code Online (Sandbox Code Playgroud)

在vs2010的调试版本中,结果是合理的.当我将它更改为发布版本时,我发现不是返回正确的迭代器,第二个m.find只是给了我大部分时间.我发现没有初始化问题.如何修复发布版本问题?

joh*_*ohn 5

好像你在FiveTuple对象上做了memcmp().这是未定义的行为,因为FiveTuple包含尾随垃圾字节.这些尾随垃圾字节在调试版本和发行版本中是不同的,因此您得到不同的结果.您应该重写FlowCmp,以便它不使用memcmp().

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

当然memcmp是另一个原因,因为它意味着你的代码将是不可移植的,因为它的行为将取决于你的平台的endianess.这本身就足以让我们不为此目的使用memcmp.