vector执行push_back操作异常

flyadou 2011-10-10 01:00:30
在调用vector push_back的时候,报错,代码如下:

class CTest
{
};

vector<CTest*> vecTest;
CTest* pT = NULL;
vecTest.push_back(pT); // 此处出错


// push_back函数调用时,出错的最终位置在:
_Myt& operator+=(difference_type _Off)
{ // increment by integer
_SCL_SECURE_VALIDATE(this->_Has_container());
_SCL_SECURE_VALIDATE_RANGE( // 调用该宏定义时出错
_Myptr + _Off <= ((_Myvec *)(this->_Getmycont()))->_Mylast &&
_Myptr + _Off >= ((_Myvec *)(this->_Getmycont()))->_Myfirst);
_Myptr += _Off;
return (*this);
}

从出错的地方来看,是由于push_back函数返回值时,发生越界,导致出错;但此处_Off = 0,_Myptr = vecTest.begin(),没有发生越界啊。请高人指点到底是什么原因导致这种情况的出现;

注: 该问题偶尔出现,不是每次必然出现;且调用vector.erase等操作时,也出现过类似错误,出错的位置在同一个地方:_SCL_SECURE_VALIDATE_RANGE 宏出错。
...全文
6345 51 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
51 条回复
切换为时间正序
请发表友善的回复…
发表回复
clmstr01 2012-10-27
  • 打赏
  • 举报
回复
另外更令人匪夷所思的是,我这个代码是以lib的形式在A项目中使用没问题,而同样是以lib的形式在B项目中使用就出现这个诡异的问题。
clmstr01 2012-10-27
  • 打赏
  • 举报
回复
我也遇到了与你一样的问题,也是在release下挂在:
_SCL_SECURE_VALIDATE(this->_Has_container());
而且只有在release下才产生该问题,debug下没问题。
另外我跟你一样使用的是VS2008的编辑器,打了SP1的补丁.
而且我不会是犯你的错误,因为我的代码是这样的:
class A{
static std::vector<A*> m_vA;
}
class B : public A{
在构造函数中push
B(){
m_vA.push_back(this);
}
}
这样是不可能有不能转换的问题。
猛哥哥8888 2012-08-17
  • 打赏
  • 举报
回复
我的代码在vc6.0里能运行,但在vs2008里面就会出现楼主说的错误,很怪异
欢_欢 2012-07-31
  • 打赏
  • 举报
回复
刚刚遇到了个类似的错菜鸟使用的不多,正在努力解决中、。、、、、
screwzm 2011-12-02
  • 打赏
  • 举报
回复
学习!!!
我也遇见类似问题,根据lz提供的信息看看去!
flyadou 2011-10-14
  • 打赏
  • 举报
回复
引用44楼ri_aje:
经常见有人说 C++ 的 xxx_cast 很恶心,可是不得不承认,这种看似很恶心的东西,能够有效的防止一些更恶心的问题。

——对于刚被更恶心过的我来说,xxx_cast现在已经变得非常亲切了。
flyadou 2011-10-13
  • 打赏
  • 举报
回复
[Quote=引用 39 楼 ri_aje 的回复:]

引用 32 楼 flyadou 的回复:

引用 29 楼 ri_aje 的回复:

引用 28 楼 flyadou 的回复:

引用 27 楼 pengzhixi 的回复:
你把完整代码发出来吧,我也有vs2008

void HgiBaseLayer::PushLensLayer(HgiBaseLayer* bsLayer)
{
m_lensLayer.push_bac……
[/Quote]

ri_aje在39楼分析的相当精辟和正确,问题的原因也找到了:
出错的vector m_lensLayer属于类HgiBaseLayer的一个成员,在调用m_lensLayer.push_back()前,我错误的对HgiBaseLayer进行了强制类型转换:
HgiBaseLayer* bsLayer = new HgiBaseLayer;
((HgiPrimeLayer*)bsLayer)->ProvokeFunc();
HgiPrimeLayer和HgiBaseLayer继承自同一父类HgiLayer,但是彼此为兄弟类,并无继承关系。HgiPrimeLayer::ProvokeFunc()中修改了一个HgiPrimeLayer独有的成员变量,该成员变量在HgiBaseLayer并不存在,因此就造成HgiBaseLayer中m_lensLayer的损坏。
而为什么问题只在RELEASE中出现,且时有时无,ri_aje在39楼做了很好的解释!

修改了这个错误后,问题不再重现。
自己的失误造成这个问题,很惭愧啊!感谢ri_aje,提供了很好的解决问题的思路,分是你的了!

呵呵,后面阅读帖子的人注意两点,我血和泪的教训:
1.强制类型转换要谨慎!
2.出错的地方不一定在报错的地方,很可能由于其他地方造成数据损毁,导致出错!
ri_aje 2011-10-13
  • 打赏
  • 举报
回复
sorry,上面我说的类继承结构打错了,应该是这样的。

HgiPrimeLayer : HgiLayer
HgiBaseLayer : HgiLayer

ri_aje 2011-10-13
  • 打赏
  • 举报
回复
[Quote=引用 43 楼 flyadou 的回复:]
……
HgiBaseLayer* bsLayer = new HgiBaseLayer;
((HgiPrimeLayer*)bsLayer)->ProvokeFunc();
HgiPrimeLayer和HgiBaseLayer继承自同一父类HgiLayer,但是彼此为兄弟类,并无继承关系。HgiPrimeLayer::ProvokeFunc()中修改了一个HgiPrimeLayer独有的成员变量,该成员变量在HgiBaseLayer并不存在,因此就造成HgiBaseLayer中m_lensLayer的损坏。
……
[/Quote]
恭喜楼主问题解决了。
另外说一个小建议,如果我没理解错的话,楼主的类体系是这样的。
HgiPrimeLayer : HgiBaseLayer
HgiBaseLayer : HgiBaseLayer
然后这句出错了,((HgiPrimeLayer*)bsLayer)->ProvokeFunc();
但错误很隐蔽,不过 C++ 有专门防此类错误的方法,就是 dynamic_cast
如果你这样写你的程序
if (HgiPrimeLayer* const pHgiPrimeLayer = dynamic_cast<HgiPrimeLayer*>(bsLayer))
{
pHgiPrimeLayer->ProvokeFunc();
}
有问题的那句压根就不会执行。
经常见有人说 C++ 的 xxx_cast 很恶心,可是不得不承认,这种看似很恶心的东西,能够有效的防止一些更恶心的问题。
flyadou 2011-10-12
  • 打赏
  • 举报
回复
引用35楼zimmermanlin:
看楼主的这些提示,有可能是掉入了vector的erase()陷阱中了。erase()掉一个后元素后,特别当此元素是指针时,因为erase的原理,将要删除的元素的后面那部分前移,最后再删除后面的,如果是指针有可能那些对象的内存被释放了,即使把对象地址前移了,已经没有意义了。访问内存出错。

不是很理解你的说法,erase操作时,会访问vector中的指针所指向的内存么?
下面的操作,只要满足后一个条件,是不是就一定不会出错呢?
vec.erase(vec.begin() + index); // index < vec.size()
zimmermanlin 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 flyadou 的回复:]

引用 29 楼 ri_aje 的回复:

引用 28 楼 flyadou 的回复:

引用 27 楼 pengzhixi 的回复:
你把完整代码发出来吧,我也有vs2008

void HgiBaseLayer::PushLensLayer(HgiBaseLayer* bsLayer)
{
m_lensLayer.push_back(bsLayer); // error
}
……
[/Quote]


看楼主的这些提示,有可能是掉入了vector的erase()陷阱中了。erase()掉一个后元素后,特别当此元素是指针时,因为erase的原理,将要删除的元素的后面那部分前移,最后再删除后面的,如果是指针有可能那些对象的内存被释放了,即使把对象地址前移了,已经没有意义了。访问内存出错。

pengzhixi 2011-10-12
  • 打赏
  • 举报
回复
考虑下迭代器失效的问题吧。
flyadou 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 heishanyizu 的回复:]

void HgiBaseLayer::PushLensLayer(HgiBaseLayer* bsLayer)
{
m_lensLayer.push_back(bsLayer); // error
}

这个函数就是出错的地方,进入该函数前程序运行都是没问题的,该函数之前的运行代码和vec……
[/Quote]

楼主 HgiBaseLayer 你这个类是不是释放掉了 然后还……
[/Quote]

HgiBaseLayer类的this指针正常
flyadou 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 ri_aje 的回复:]

引用 28 楼 flyadou 的回复:

引用 27 楼 pengzhixi 的回复:
你把完整代码发出来吧,我也有vs2008

void HgiBaseLayer::PushLensLayer(HgiBaseLayer* bsLayer)
{
m_lensLayer.push_back(bsLayer); // error
}

这个函数就是出错的地方,进入该函数前程序……
[/Quote]

ri_aje正解,错误应该不是vector引起的,而是我本身的问题;现在出错的地方就在vector上,只能从上面获取线索了。
最近的测试发现两个问题:
1.DEBUG版本中,不会报错
2.push_back报错时,都是vector.capacity() == vector.size()时,也即系统给vector扩展内存空间时出错;奇怪的是,在出错的地方,vector默认分配的capacity() == 2。当我在类初始化时,设定vector.reserve(100),则其后push_back()将不再出错; 但是在其他地方出现调用vector.erase的错误,错误指向的最终位置也是iterator的操作符重载函数 operator+=。erase的调用方式:
vec.earse(vec.begin() + index); // index < vec.size()

push_back在类初始化时手动用reserve扩容后不出错,而在自动扩容时出错;因此我想可能是程序在其他地方的内存分配和释放出了问题,导致vector自动扩展时出现越界等问题;另外问题只在RELEASE中出现,可能和变量初始化有关系,将重点检查下这方面的原因。
heishanyizu 2011-10-12
  • 打赏
  • 举报
回复
void HgiBaseLayer::PushLensLayer(HgiBaseLayer* bsLayer)
{
m_lensLayer.push_back(bsLayer); // error
}

这个函数就是出错的地方,进入该函数前程序运行都是没问题的,该函数之前的运行代码和vec……
[/Quote]

楼主 HgiBaseLayer 你这个类是不是释放掉了 然后还调用PushLensLayer
zhenghang_zdwxgd 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 ri_aje 的回复:]

你自建的程序没问题,充分说明不是 std::vector 造成的问题,反过来间接说明原来程序挂掉是你自己的问题。你光贴这一点代码是没有用的,我在 14# 已经说了,问题肯定不在 std::vector::push_back 里,虽然最后程序挂掉的点在里面。调程序千万别有先入为主的偏见,认为错误一定在那,或一定不在那。你要是能对程序了如指掌,知之甚切,也根本就不会出错误;即然出错了,还是谦虚谨慎为妙。我昨天刚帮别人调了个程序,那人斩钉截铁的跟我说一定不是那那的错误,我想看一下那部分源码的时候还一脸不耐烦,最后就是在那里找到的错误。

我也理解楼主工程大,贴上来不现实,楼主这种情况是最爱莫能助的了。我建议楼主好好理清程序的思路和逻辑,这比天天盯着 debugger 更管用。另外再强调一下错误不在 std::vector::push_back,楼主大可不必在那里浪费时间了。
[/Quote]

赞,这位仁兄讲的很清楚了。
jhzlf 2011-10-12
  • 打赏
  • 举报
回复
楼主这一部分代码没看出问题
earse之后迭代器失效不知道考虑没有
出错的地方应该是别的地方对这个vector进行了操作吧
还是需要看完整的代码
Qlaiaqu 2011-10-12
  • 打赏
  • 举报
回复
容器压入的是指针,要保证好指针指向数据的有效性。其它实在看不出来问题,楼主可能用错了
ri_aje 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 flyadou 的回复:]

引用 29 楼 ri_aje 的回复:

引用 28 楼 flyadou 的回复:

引用 27 楼 pengzhixi 的回复:
你把完整代码发出来吧,我也有vs2008

void HgiBaseLayer::PushLensLayer(HgiBaseLayer* bsLayer)
{
m_lensLayer.push_back(bsLayer); // error
}
……
2.push_back报错时,都是vector.capacity() == vector.size()时,也即系统给vector扩展内存空间时出错;奇怪的是,在出错的地方,vector默认分配的capacity() == 2。当我在类初始化时,设定vector.reserve(100),则其后push_back()将不再出错; 但是在其他地方出现调用vector.erase的错误,错误指向的最终位置也是iterator的操作符重载函数 operator+=。erase的调用方式:
vec.earse(vec.begin() + index); // index < vec.size()
push_back在类初始化时手动用reserve扩容后不出错,而在自动扩容时出错;因此我想可能是程序在其他地方的内存分配和释放出了问题,导致vector自动扩展时出现越界等问题;另外问题只在RELEASE中出现,可能和变量初始化有关系,将重点检查下这方面的原因。
[/Quote]
我倒是觉得是那里没注意内存越界访问直接覆盖了 vec 的信息,使得再次调用 push_back 时,vec 已经处于 corrupted 的状态了,因此产生错误。举个很简单的例子,

int a [10];
std::vector<int*> vec;
a[10] = a[11] = a[12] = ... = 0; // memory corruption

如果 vec 在栈上地址处于数组 a 的上方,那么 a[10] ... 那句的越界访问会强制覆盖 vec 中的信息,导致其数据结构破坏,下回再调用其方法时就要完蛋了,而且是完蛋在 vector 的成员函数里,但实际上出错误的并不是 std::vector。
这也间接符合 debug 不挂的现象,因为 debug 版通常要记录多余的信息,很可能在 std::vector 具体的实现中,那些最终在 release 版引起错误的成员变量前面有多余的变量定义。这些多余的 debug 变量实际上充当了重要成员变量的盾牌,使得越界访问并没有碰到真正有用的变量,因此不会挂。
建议楼主查一下具体代码中,定义在 vec 前面的东西,看看它们是不是那里引起了越界问题。
flyadou 2011-10-12
  • 打赏
  • 举报
回复
[Quote=引用 37 楼 mingliang1212 的回复:]

引用 21 楼 flyadou 的回复:
有一个编译器的设置不知道会不会有问题:我用的是Release版本调试程序,开启了Generate Debug Info,且生成了pdb文件,即在Link/Debugging下,设置Generate Debug Info为Yes(/Debug),Generate Program Database File设为$(TargetDir)$(TargetNam……
[/Quote]
是的,我有在DEBUG下调试,调试结果是正常的,没有出错; 就是说错误只在用RELEASE版本进行调试时出现;对于用RELEASE编译出来的程序,如果不调试,直接运行,同样也会出错;
加载更多回复(30)

65,202

社区成员

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

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