STL vector出现的错误

duquanxi 2009-06-08 09:22:18
我有这样一段代码:
bool CCredentila::AddToCredentialList(BYTE inBuf[])
{
Credential Creden;
Creden.CredPack.UnPack(inBuf);

WaitForSingleObject(CreMutex,INFINITE);
Credentials.push_back(Creden);
ReleaseMutex(CreMutex);

return true;
}

当在多线程中,多次执行这个函数时,会不定时的出现 应用程序强制关闭对话框。
Credentials是个全局变量,其定义:std::vector< Credential > Credentials; //记录凭证的结构
...全文
398 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
dahaiI0 2011-08-31
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 hdqqq 的回复:]
楼主对vector和iterator实现不是很了解, vector对内存的使用是翻倍递增的,比如先new 出16个元素的大小,当16个满后,就new出32个元素的大小,然后把原先的16个复制过去,再释放原先的内存,32满了,再翻倍,至于iterator,是对内部使用的指针的一种封装,实现了->, = 操作符重载, 但是因为vector的内存增量机制,所有,每当vector push_back元素的……
[/Quote]
刚看了下代码,vector对内存的使用并不是翻倍,而是容量不够时涨50%,比如NEW16个字节,当size》=容量时,容量=容量+容量*0.5,即16+16*0.5=24个字节。
dahaiI0 2011-08-30
  • 打赏
  • 举报
回复
学习了。。。
hdqqq 2009-11-21
  • 打赏
  • 举报
回复
所以在大数据量的情况下,vector每次push_back所花费的时间不是固定的,可能会发生大块内存拷贝,除非你预先作了reserve,相对来说,list的push_back花费的时间可以算是常量. 但使用vector的好处是可以随机访问,而 list只能顺序访问.
hdqqq 2009-11-21
  • 打赏
  • 举报
回复
楼主对vector和iterator实现不是很了解, vector对内存的使用是翻倍递增的,比如先new 出16个元素的大小,当16个满后,就new出32个元素的大小,然后把原先的16个复制过去,再释放原先的内存,32满了,再翻倍,至于iterator,是对内部使用的指针的一种封装,实现了->, = 操作符重载, 但是因为vector的内存增量机制,所有,每当vector push_back元素的时候,使用的内存块可能发生调整,所以,vector的iterator不能用于递归函数和多线程,因为当递归调用push_back或者其他线程push_back, 原先iterator引用的 指针就无效了,因为该块内存可能已经被释放.
sendwb 2009-08-24
  • 打赏
  • 举报
回复
我现在遇到了同样的问题,而且我的确push_back里存储的就是对象指针,但同样会在这个位置报错,而且很有规律,就是压了第32个对象指针以后,压第33个就会报错
bobohack 2009-06-12
  • 打赏
  • 举报
回复
路过
hdqqq 2009-06-12
  • 打赏
  • 举报
回复
*begin()+i 不一定是线程安全的.
jingzhongrong 2009-06-10
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 hdqqq 的回复:]
push_back 的时候,会导致 iterator 无效, 因为可能会复制内存, 因此,如果其它线程正在读取数据, 当前使用的iterator 就无效了. 改用list 较好.
[/Quote]

对于vector,可以不使用iterator来遍历,可以直接使用下标或者使用*begin()+i
sunlin7 2009-06-09
  • 打赏
  • 举报
回复
SET不支持多线程,所以得自己辛苦点来处理线程同步的操作。
hdqqq 2009-06-09
  • 打赏
  • 举报
回复
比如你在某个线程里面
for(it = v.begin(); it != v.end(); it++)
{
//do something;
}

但在另一个线程里面 做了push_back,
那么
it++ 可能会有问题, 因为 push_back后, it 可能无效.
hdqqq 2009-06-09
  • 打赏
  • 举报
回复
push_back 的时候,会导致 iterator 无效, 因为可能会复制内存, 因此,如果其它线程正在读取数据, 当前使用的iterator 就无效了. 改用list 较好.
jingzhongrong 2009-06-08
  • 打赏
  • 举报
回复
1、vector中保存指针
2、在push_back操作时,如果vector空间不够,会导致内存的重新分配,多线程情况下读取可能会出现问题。
菜牛 2009-06-08
  • 打赏
  • 举报
回复
最好用指针保存。
leither 2009-06-08
  • 打赏
  • 举报
回复
赞成17楼的方法,只保存类指针,这种不涉及类的深复制问题。
即将全局变量Credentials定义为:std::vector < Credential* > Credentials

或者重写Credential的一个构造函数

Credential::(const Credential & p)
{ //复制所有数据
}


再或者Credential类不要涉及任何内存申请,删除操作(这估计比较难)
duquanxi 2009-06-08
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 wocow3 的回复:]
inBuf[]是否是其他线程的buffer?
[/Quote]
不是其他线程的
华亭真人 2009-06-08
  • 打赏
  • 举报
回复
F5调试运行
wocow3 2009-06-08
  • 打赏
  • 举报
回复
inBuf[]是否是其他线程的buffer?
dong364 2009-06-08
  • 打赏
  • 举报
回复
建议vector中保存指针,不要保存类对象;估计是Creden.CredPack.UnPack(inBuf); 中没有考虑多线程的情况
oyljerry 2009-06-08
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 duquanxi 的回复:]
引用 14 楼 wocow3 的回复:
push_back是调用类的拷贝构造函数push一个副本

push_back局部变量有问题只能说明你的拷贝构造并不是深拷贝,这个类不适用于vector容器


那是说我写个拷贝构造函数就应当能解决问题是吧
[/Quote]
深拷贝就是把所有数据内容都拷贝进vector,但是你修改vector的时候,其他地方不能读取它,要做同步
duquanxi 2009-06-08
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wocow3 的回复:]
push_back是调用类的拷贝构造函数push一个副本

push_back局部变量有问题只能说明你的拷贝构造并不是深拷贝,这个类不适用于vector容器
[/Quote]
那是说我写个拷贝构造函数就应当能解决问题是吧
加载更多回复(14)

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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