C++ 迭代器大小为4的读取无效

C++ 迭代器大小为4的读取无效,c++,dictionary,iterator,valgrind,C++,Dictionary,Iterator,Valgrind,为什么Valgrind会在下一行中指示大小为4的无效读取 for (map<uint16_t, SPacket *>::iterator it = m_PacketMap.begin() ; it != m_PacketMap.end(); ++it) { if (it->first < ackNumber) { if (it->second->data) delete [] it->second->data;

为什么Valgrind会在下一行中指示大小为4的
无效读取

for (map<uint16_t, SPacket *>::iterator it = m_PacketMap.begin() ; it != m_PacketMap.end(); ++it) 
{
    if (it->first < ackNumber)
    {
        if (it->second->data) delete [] it->second->data;
        if (it->second) delete it->second;
        m_PacketMap.erase(it);
    }
}
这就是SPacket和m_PacketMap的定义

typedef struct SPacket
{
    uint8_t * data;
    size_t size;
    timeval tval;
} SPacket;
map<uint16_t, SPacket *> m_PacketMap;
typedef结构SPacket
{
uint8_t*数据;
大小;
蒂梅瓦尔·特瓦尔;
}斯帕克特;
地图m_PacketMap;

我的迭代器有问题吗?\u Rb\u tree\u increment中可能有问题,或者完全是其他问题?

必须小心地从
for
循环中删除容器元素

你必须做到:

map<uint16_t, SPacket *>::iterator it = m_PacketMap.begin()
while ( it != m_PacketMap.end() ) 
{
    if (it->first < ackNumber)
    {
        if (it->second->data) delete [] it->second->data;
        if (it->second) delete it->second;
        // it updated by erase, no need to increment
        it = m_PacketMap.erase(it);
    }
    else
    {
        // move to next item
        ++it;
    }
}
map::iterator it=m_PacketMap.begin()
while(it!=m_PacketMap.end())
{
如果(它->第一个<确认号)
{
如果(it->second->data)删除[]it->second->data;
如果(它->秒)删除它->秒;
//它通过擦除更新,无需增加
it=m_PacketMap.erase(它);
}
其他的
{
//移到下一项
++它;
}
}
这就是删除容器中某些元素的循环必须被写入的方式(对set、vector等也适用)

对于映射,上面的代码仅适用于C++11。如果您使用早期版本,根据(未测试),您应该执行以下操作:

for ( map<uint16_t, SPacket *>::iterator it = m_PacketMap.begin(); it != m_PacketMap.end();  ) 
{
    if (it->first < ackNumber)
    {
        if (it->second->data) delete [] it->second->data;
        if (it->second) delete it->second;
        // it updated by erase, no need to increment
        m_PacketMap.erase(it++);
    }
    else
    {
        // move to next item
        ++it;
    }
}
for(map::iterator it=m_PacketMap.begin();it!=m_PacketMap.end();)
{
如果(它->第一个<确认号)
{
如果(it->second->data)删除[]it->second->data;
如果(它->秒)删除它->秒;
//它通过擦除更新,无需增加
m_PacketMap.erase(it++);
}
其他的
{
//移到下一项
++它;
}
}

因为删除项目,然后增加项目(您最后对
for
循环所做的操作)将使元素松散,并可能传递
m_PacketMap.end()
(然后使循环覆盖的项目超出容器的限制)如果从容器中删除最后一个元素。

for
循环中删除容器元素时必须小心

你必须做到:

map<uint16_t, SPacket *>::iterator it = m_PacketMap.begin()
while ( it != m_PacketMap.end() ) 
{
    if (it->first < ackNumber)
    {
        if (it->second->data) delete [] it->second->data;
        if (it->second) delete it->second;
        // it updated by erase, no need to increment
        it = m_PacketMap.erase(it);
    }
    else
    {
        // move to next item
        ++it;
    }
}
map::iterator it=m_PacketMap.begin()
while(it!=m_PacketMap.end())
{
如果(它->第一个<确认号)
{
如果(it->second->data)删除[]it->second->data;
如果(它->秒)删除它->秒;
//它通过擦除更新,无需增加
it=m_PacketMap.erase(它);
}
其他的
{
//移到下一项
++它;
}
}
这就是删除容器中某些元素的循环必须被写入的方式(对set、vector等也适用)

对于映射,上面的代码仅适用于C++11。如果您使用早期版本,根据(未测试),您应该执行以下操作:

for ( map<uint16_t, SPacket *>::iterator it = m_PacketMap.begin(); it != m_PacketMap.end();  ) 
{
    if (it->first < ackNumber)
    {
        if (it->second->data) delete [] it->second->data;
        if (it->second) delete it->second;
        // it updated by erase, no need to increment
        m_PacketMap.erase(it++);
    }
    else
    {
        // move to next item
        ++it;
    }
}
for(map::iterator it=m_PacketMap.begin();it!=m_PacketMap.end();)
{
如果(它->第一个<确认号)
{
如果(it->second->data)删除[]it->second->data;
如果(它->秒)删除它->秒;
//它通过擦除更新,无需增加
m_PacketMap.erase(it++);
}
其他的
{
//移到下一项
++它;
}
}

因为如果从容器中删除最后一个元素,则删除该项然后再增加它(您最终对
for
循环所做的操作)将使元素松散,并可能传递
m\u PacketMap.end()
(然后使循环覆盖项超出容器的限制)。

您删除了一个元素,这使得
无效,然后您增加
。不能递增无效迭代器

使用
-D_GLIBCXX_DEBUG
重建代码将启用libstdc++调试模式,该模式将在无效迭代器操作时中止


与valgrind错误无关,在使用
delete
之前,您不需要测试指针是否不为null,因为在null指针上使用
delete
是安全的(它会检查null,所以您只是添加不必要的重复检查)。

删除元素,这会使
无效,然后你增加它
。不能递增无效迭代器

使用
-D_GLIBCXX_DEBUG
重建代码将启用libstdc++调试模式,该模式将在无效迭代器操作时中止


与valgrind错误无关,在使用
delete
之前,您不需要测试指针是否不为null,因为在null指针上使用
delete
是安全的(它会检查null,所以您只是添加不必要的重复检查)。

是的。如果地图条目与密钥匹配,我将删除它们。我将把主体添加到原始问题中。啊。我想我明白你的意思了。容器收缩时迭代器如何工作。是的。如果地图条目与密钥匹配,我将删除它们。我将把主体添加到原始问题中。啊。我想我明白你的意思了。当容器正在收缩时,迭代器如何工作。m_SentPacketMap是一个输入错误
m_PacketMap.erase(it++)
be
m_PacketMap.erase(it)
it=m_PacketMap.erase(it)m_PacketMap.erase(it++)it=m_PacketMap.erase(it);
当时不应编译)m_SentPacketMap是一个打字错误,如果
m_PacketMap.erase(it++)
be
m_PacketMap.erase(it)
it=m_PacketMap.erase(it)m_PacketMap.erase(it++)用于早期版本(
it=m_PacketMap.erase(it);
不应编译)