作者dryman (dryman)
看板EE_DSnP
标题[问题] 挂在非常奇怪的地方
时间Thu Dec 10 23:31:18 2009
我的程式在AdtTest::getPos 125行会出问题
AdtTest::getPos (this=0x80597b8, pos=0) at adtTest.h:124
124 size_t i = 0;
125 AdtType<AdtTestObj>::iterator li = _container.begin();
li 的内容没有被更改到(变成垃圾)
我猜测可能是 = 或是iterator 的 constructor(const iterator& i)出问题
可是似乎都不是
而且在print的时候也有叫到
AdtType<AdtTestObj>::iterator li = _container.begin();
就没有出任何问题..
以下是我debug的结果:
98 if (_container.erase(getPos(pos))) --s;
(gdb) s 进入getPOs(pos)
AdtTest::getPos (this=0x80597b8, pos=0) at adtTest.h:124
124 size_t i = 0;
125 AdtType<AdtTestObj>::iterator li = _container.begin();
(gdb) s 进入呼叫li = _container.begin()
BSTree<AdtTestObj>::begin (this=0x80597b8) at ../../include/bst.h:254
254 if (_begin_changed){
260 return _begin;
261 }
(gdb) 我有去检查begin有没有更动过,所以可以直接O(1)
此时的begin是正确的
iterator (this=0xbf954eb8, i=@0x80597b8) at ../../include/bst.h:140
140 iterator(const iterator& i): _dummy(false) {
141 _his = new HisNode<T>[ARR_CAPACITY(i._his)];
142 *this = i;
143 }
现在要做出一个新的iterator给外面的li
(gdb) p *this._his[_pos].bst_node
$1 = {
_data = {
_data = 394,
static _dataRange = 1000
},
_leaf_l = 0x0,
_leaf_r = 0x9bba618
}
这时*this的内容是正确的
(gdb) s
AdtTest::getPos (this=0x80597b8, pos=0) at adtTest.h:126
126 AdtType<AdtTestObj>::iterator lj = _container.end();
回到getPos..(显示了下一行,不过我们关心的是上一行的li)
(gdb) p li
$2 = {
_pos = 3214233272,
_dummy = 184,
_his = 0x0
}
印出li...里面的内容是垃圾..
(gdb) n
128 return li;
(gdb) p lj
$3 = {
_pos = 1,
_dummy = true,
_his = 0x9bbc6cc
}
同样的东西lj就是可以正常复制,资料是正确的 = =|||
想了很久还是不懂为什麽会变这样
烦请高手解答<(_ _)>
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 114.45.169.1
1F:推 Neilhahaha:142的*this=i删掉看看? 12/10 23:40
2F:→ dryman:不行啊..那样*this内容就没被改到了 12/10 23:45
3F:→ dryman:那样的话*this里就都是垃圾了.. 12/10 23:45
4F:推 timrau:iterator::operator=()长什麽样子? 12/10 23:46
5F:→ dryman:理论上这个*this应该就是li才对... 12/10 23:46
iterator& operator = (const iterator& i){
if (ARR_CAPACITY(_his)!=ARR_CAPACITY(i._his)){
delete[]_his;
_his = new HisNode<T>[ARR_CAPACITY(i._his)];
}
for (_pos = 0; _pos <= i._pos; ++_pos)
_his[_pos] = i._his[_pos];
--_pos;
_dummy = i._dummy;
return *this;
}
没有写注解可能会有点难看懂..
不过我检查过从=出来的*this和在constructor的*this内容都是正确的
尤其是constructor的*this是正确的最为诡异
因为那个*this不是应该就是li本身吗?
125 AdtType<AdtTestObj>::iterator li = _container.begin();
※ 编辑: dryman 来自: 114.45.169.1 (12/10 23:49)
补充诡异点之二:127行会被自动略过..
我将125,126行位置对调,以测试adtTest是不是有一起被complie而不只是物件
Breakpoint 1, AdtTest::getPos (this=0x80597f8, pos=0) at adtTest.h:124
124 size_t i = 0;
(gdb) l
119
120 #ifdef RANDOM_ACCESS
121 if (pos >= _container.size()) return _container.end();
122 return (_container.begin() + pos);
123 #else
124 size_t i = 0;
125 AdtType<AdtTestObj>::iterator lj = _container.end();
126 AdtType<AdtTestObj>::iterator li = _container.begin();
127 while ((li != lj) && (i++ != pos)) ++li;
128 return li;
(gdb) n
125 AdtType<AdtTestObj>::iterator lj = _container.end();
(gdb)
126 AdtType<AdtTestObj>::iterator li = _container.begin();
(gdb)
128 return li;
超毛的,127行gdb怎麽完全没有去动!!
通常不都应该是先列印出127行
然後next後会显示记忆体区段错误之类的吗?
结果居然被完全省略掉了..<囧>
※ 编辑: dryman 来自: 114.45.169.1 (12/10 23:56)
※ 编辑: dryman 来自: 114.45.169.1 (12/10 23:57)
※ 编辑: dryman 来自: 114.45.169.1 (12/10 23:58)
6F:推 timrau:不负责任猜测:iterator::operator=()里面 12/11 00:02
7F:→ timrau:delete[] _his;前请先检查if(NULL != _his) 12/11 00:03
8F:→ timrau:BTW,如果是我会用constructor来实做operator=()而非相反 12/11 00:04
9F:→ timrau:真的搞不定就valgrind跑一发,先把warning/error清乾净再说 12/11 00:04
10F:推 ric2k1:copy constructor 里面又有 *this = li... 恐怕会挂吧! 12/11 00:06
11F:→ ric2k1:请做 member-wise 的 assignment... 12/11 00:06
12F:推 timrau:这里凑巧是丢reference进去丢reference出来 不然早就 12/11 00:08
13F:→ timrau:无穷递回了吧 @@ 12/11 00:09
14F:推 ric2k1:我还是觉得应该是不行,compile 没有 warning 吗? 12/11 00:10
15F:推 timrau:我觉得compile不会有问题,多少default constructor 12/11 00:11
16F:→ timrau:都是写个initialize();了事也活得好好的.... 12/11 00:12
17F:→ dryman:compile没有error..我试试看将constructor来做= 12/11 00:16
18F:→ dryman: 用 12/11 00:17
copy constructor 改成
iterator(const iterator& i): _dummy(false) {
_his = new HisNode<T>[ARR_CAPACITY(i._his)];
for (_pos = 0; _pos <= i._pos; ++_pos)
_his[_pos] = i._his[_pos];
--_pos;
_dummy = i._dummy;
}
还是没有用..
li还是垃圾,127行也是直接略过
orz|||
※ 编辑: dryman 来自: 114.45.169.1 (12/11 00:22)
19F:推 ric2k1:我的意思是: iterator(...i):_pos(i.pos), _dummy(false), 12/11 00:21
20F:→ ric2k1:_his(i._his) { ....} ^_pos 12/11 00:21
21F:推 ric2k1:然後里面不要在 *this = i 12/11 00:21
22F:推 ric2k1:cout 大法搬出来,看它到底呼叫了什麽东西... 12/11 00:29
23F:→ dryman:_his是一个阵列,所以用老师的方法好像不太容易改.. 12/11 00:29
24F:推 ric2k1:不过你的 copy constructor 的定义好奇怪,跟一般的 = 的意 12/11 00:30
25F:→ dryman:_his(i.his)的部份 12/11 00:30
26F:→ ric2k1:思不同,会让 code 变得比较不直观... 12/11 00:30
27F:→ dryman:因为要把整个_his <-history的阵列一起复制的关系.. 12/11 00:34
28F:推 timrau:还是怀疑memory被写烂了.......导致code乱跳 这是有可能的 12/11 00:48
29F:推 Neilhahaha:阵列不能直接复制吗? 我觉得问题应该就是教授说的那样 12/11 00:52
30F:推 Neilhahaha:*this=i会再跑去叫overload=感觉就蛮怪的 12/11 00:54
31F:→ dryman:所以我就改成没有用*this=i的版本了呀.. 12/11 00:58
32F:→ dryman:我也觉得应该是哪里memory出问题,不过最囧的就是 12/11 00:59
33F:→ dryman:不知道为什麽还在copy constructor里面时*this是正确的.. 12/11 00:59
34F:推 ric2k1:ARR_CAPACITY(i._his) 是多少啊? 觉得你的 array copy 怪 12/11 01:06
35F:→ ric2k1:怪的... _pos 最好是 pass-the-end,否则一开始它是要指到 12/11 01:07
36F:→ ric2k1:哪里? 12/11 01:07
我的_his是一个dynamic array
这里的ARR_CAPACITY呼叫的是array前纪录大小的那一块
改用cout大法後,发生很怪异的事..就是li居然印出了正确的值(翻桌)
Constructing li..
In copy constructor.._pos = 1
data is 394
li._pos = 1
In copy constructor.._pos = 1
data is 911
In copy constructor.._pos = 1
data is 394
(我把end(),begin()的顺序又换了回来,911的那个是copy end的部份)
当然在下一行它还是挂掉了
不过感觉像是gdb没有正确的抓到值...有没有这麽误导的啊
囧
※ 编辑: dryman 来自: 114.45.169.1 (12/11 01:17)
37F:→ dryman:超级大乌龙..(翻) 不过下一行我print ++都没事这里会挂 12/11 01:19
38F:→ dryman:也很奇怪就是了.. 12/11 01:20
39F:推 Neilhahaha:所以OK了? 12/11 01:21
40F:→ dryman:no... 12/11 01:34
我记得上课有上过
iterator operator ++(int)
应该是只有在li++的时候才会呼叫到
可是我从头到尾都只有用++it,却会呼叫到++(int) (我用了cout大法来确认)
这..怎麽会这麽奇怪..
它应该是挂在++li的地方,继续cout检查中..
※ 编辑: dryman 来自: 114.45.169.1 (12/11 01:40)