C++ List 元素删除后,出错

aility 2009-04-19 07:03:28
最近用了List来处理客户端上线及非法离线问题;
测试时:A用户正常上线,服务器端正常显示了。 然后A非法离线
第一次客户端非法离线后,用户确实从列表删除了,但是由于元素只有1个,却继续for 循环,导致程序非法操作

服务器端的部分代码如下:
出错的代码主要是元素删除了,已经没有数据了,但是还继续下一轮循环,导致(*UserIterator)取数据时内存非法访问,请问各个大虾,以下代码应该怎样修改?

typedef list<stUserListNode *> UserList;
for (UserList::iterator UserIterator = pThis->ClientList.begin();
UserIterator != pThis->ClientList.end();
++UserIterator) //这里面ClientList已经有一个元素
{
if (*UserIterator !=NULL)
{
//调试时看的测试数据start .............
currentuser->ip = (*UserIterator)->ip; //第一次客户端非法离线后,用户确实从列表删除了,但是由于元素只有1个,却继续for 循环,导致程序非法操作
currentuser->port = (*UserIterator)->port;
strcpy(currentuser->userName , (*UserIterator)->userName);
currentuser->dwLastActiveTime = (*UserIterator)->dwLastActiveTime;
DWORD dwTemp = (*UserIterator)->dwLastActiveTime;
//调试时看的测试数据end .............
if ((dwTick - dwTemp) >= (2 * 30 * 1000)) //大于2次轮询间隔都不在的话,则表示已经离线了
{
pThis->ClientList.remove(*UserIterator); //从用户列表中删除该用户
}
}
}
...全文
697 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
术木 2009-04-21
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 xuhb95083023 的回复:]
effective stl

条款33:提防在指针的容器上使用类似remove的算法
[/Quote]

这本书应该看下

amossavez 2009-04-21
  • 打赏
  • 举报
回复
迭代器失效??!
tianya0609 2009-04-21
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 aility 的回复:]
引用 14 楼 zhh157 的回复:
考虑到remove操作可能会使迭代器失效
因此需要对迭代器先做++操作

C/C++ code
pThis->ClientList.remove(*UserIterator++); //从用户列表中删除该用户


非常感谢,正解
[/Quote]
这些事说在算法函数上的,成员函数跟算法实现的不一样,应该考虑下会不会有同样的问题。
lori227 2009-04-21
  • 打赏
  • 举报
回复


for (UserList::iterator UserIterator = pThis->ClientList.begin();
UserIterator != pThis->ClientList.end();
) //这里面ClientList已经有一个元素
{
if (*UserIterator !=NULL)
{
//调试时看的测试数据start .............
currentuser->ip = (*UserIterator)->ip; //第一次客户端非法离线后,用户确实从列表删除了,但是由于元素只有1个,却继续for 循环,导致程序非法操作
currentuser->port = (*UserIterator)->port;
strcpy(currentuser->userName , (*UserIterator)->userName);
currentuser->dwLastActiveTime = (*UserIterator)->dwLastActiveTime;
DWORD dwTemp = (*UserIterator)->dwLastActiveTime;
//调试时看的测试数据end .............
if ((dwTick - dwTemp) >= (2 * 30 * 1000)) //大于2次轮询间隔都不在的话,则表示已经离线了
{
UserIterator = pThis->ClientList.erase(UserIterator); //从用户列表中删除该用户
}
else
{
++UserIterator;
}
}
else
{
++UserIterator;
}

}
lori227 2009-04-21
  • 打赏
  • 举报
回复


for (UserList::iterator UserIterator = pThis->ClientList.begin();
UserIterator != pThis->ClientList.end();
) //这里面ClientList已经有一个元素
{
if (*UserIterator !=NULL)
{
//调试时看的测试数据start .............
currentuser->ip = (*UserIterator)->ip; //第一次客户端非法离线后,用户确实从列表删除了,但是由于元素只有1个,却继续for 循环,导致程序非法操作
currentuser->port = (*UserIterator)->port;
strcpy(currentuser->userName , (*UserIterator)->userName);
currentuser->dwLastActiveTime = (*UserIterator)->dwLastActiveTime;
DWORD dwTemp = (*UserIterator)->dwLastActiveTime;
//调试时看的测试数据end .............
if ((dwTick - dwTemp) >= (2 * 30 * 1000)) //大于2次轮询间隔都不在的话,则表示已经离线了
{
UserIterator = pThis->ClientList.erase(*UserIterator); //从用户列表中删除该用户
}
else
{
++UserIterator;
}
}
else
{
++UserIterator;
}

}
jhony_lee 2009-04-21
  • 打赏
  • 举报
回复
好像在哪里看见过remove()操作以后,指针自动会指向下一个位置。
xuhb95083023 2009-04-20
  • 打赏
  • 举报
回复
effective stl

条款33:提防在指针的容器上使用类似remove的算法
old-six-programmer 2009-04-20
  • 打赏
  • 举报
回复
考虑到remove操作可能会使迭代器失效
因此需要对迭代器先做++操作

pThis->ClientList.remove(*UserIterator++); //从用户列表中删除该用户
lightbear 2009-04-20
  • 打赏
  • 举报
回复
gz
jssz103b 2009-04-20
  • 打赏
  • 举报
回复

xxx::iterator it = g_xxx.begin();
for(; it != g_xxx.end();)
//if (ddddddd)
it = g_xxx.erase(it);
//else
// it++;
sbqjhipr 2009-04-20
  • 打赏
  • 举报
回复
在删除UserIterator之前要看看是否到达pThis->ClientList.end()是应该退出了。
aility 2009-04-20
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 xuhb95083023 的回复:]
effective stl

条款33:提防在指针的容器上使用类似remove的算法
[/Quote]
抽时间确实得了解了解这些细节 TKS
aility 2009-04-20
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zhh157 的回复:]
考虑到remove操作可能会使迭代器失效
因此需要对迭代器先做++操作

C/C++ code
pThis->ClientList.remove(*UserIterator++); //从用户列表中删除该用户
[/Quote]

非常感谢,正解
lizhaohu 2009-04-19
  • 打赏
  • 举报
回复
for (UserList::iterator UserIterator = pThis->ClientList.begin();
UserIterator != pThis->ClientList.end();
UserIterator++) //
wangdiao0412 2009-04-19
  • 打赏
  • 举报
回复

if ((dwTick - dwTemp) >= (2 * 30 * 1000)) //大于2次轮询间隔都不在的话,则表示已经离线了
{
if(UserIterator == pThis->ClientList.end() - 1)
{
pThis->ClientList.remove(*UserIterator);--UserIterator; //在这防止指针越界
}else
pThis->ClientList.remove(*UserIterator); //从用户列表中删除该用户
}

pengzhixi 2009-04-19
  • 打赏
  • 举报
回复
我在想是不是删除后导致迭带器失效了。
lpf000 2009-04-19
  • 打赏
  • 举报
回复
countinue;
aility 2009-04-19
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wangdiao0412 的回复:]
C/C++ codeif ((dwTick - dwTemp) >= (2 * 30 * 1000)) //大于2次轮询间隔都不在的话,则表示已经离线了
{
pThis->ClientList.remove(*UserIterator); //从用户列表中删除该用户
if(UserIterator-1 == pThis->ClientList.end()) break;//我猜的,呵呵,在这判断一下
}
[/Quote]
在这里break;的话就打断了for循环,那么又得等待一个轮询线程才能执行到for循环。
也就是说:只要碰到一个离线的,就得等到下次再轮询,效率上及准确率上,不允许。
wangdiao0412 2009-04-19
  • 打赏
  • 举报
回复
if ((dwTick - dwTemp) >= (2 * 30 * 1000)) //大于2次轮询间隔都不在的话,则表示已经离线了
{
pThis->ClientList.remove(*UserIterator); //从用户列表中删除该用户
if(UserIterator-1 == pThis->ClientList.end()) break;//我猜的,呵呵,在这判断一下
}
aility 2009-04-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 hairetz 的回复:]
引用 5 楼 aility 的回复:
前面WaitForSingleObject等东西是有的,只是代码没有贴全
不过删除的核心代码就是这些了,另外代码出错也就是 这个地方:
删除完元素后,居然还继续for循环走。。导致代码出错.
我前面很多地方删除都是用remove都没出错,只是这次唯一的却别是 remove后,继续后面元素的判断删除;以前是碰到合适的删除完毕后直接退出brek for循环


为何不删除完后break?
[/Quote]

因为,删除完一个后, 如果后续还有元素还要做比较处理。
现在我感觉的问题是,虽然remove了,但是list的总数并没有变。。我正在测试,也希望大虾,指点一二
加载更多回复(6)

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧