C++ 迭代器大小为4的读取无效
为什么Valgrind会在下一行中指示大小为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;
无效读取
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++)
bem_PacketMap.erase(it)
?it=m_PacketMap.erase(it)对于C++11,m_PacketMap.erase(it++)对于早期版本(it=m_PacketMap.erase(it);
当时不应编译)m_SentPacketMap是一个打字错误,如果m_PacketMap.erase(it++)
bem_PacketMap.erase(it)
it=m_PacketMap.erase(it)对于C++11,m_PacketMap.erase(it++)代码>用于早期版本(it=m_PacketMap.erase(it);
不应编译)