2010年6月11日星期五

Bug Series - 数组变小了

Let see look the a tree structure first:
一个Scene底下有两个geometry, 后来在Scene下还多建立了一个Skeleton来做skinning, 这个skinning与那两个geometry有关,是作用于它们上面的, 具体的skinning操作变换在各自的SkeletonReference中。
并且为了记录这个Skeleton 是操作哪些Geometry的,于是Skeleton有一个成员m_arrGeo[]是一个数组, 这个例子中记录的是两个指针.

下面的问题是: 我要删除这个skinning操作, 也就是将Skeleton和两个SkeletonReference删除掉.

code:
for (int i = 0; i < skeleton->m_arrGeo.size(); ++i) {
delete skeleton->m_arrGeo[i]->skeleton_reference;
}
delete skeleton;

这个代码段在Skeleton只作用于一个Geometry时候运行正常, 但是当作用于两个和多个Geometry时候就错误了(错误是隐晦地遗留到后面别的地方才造成的,不是在这里就造成,这才是恐怖的地方).

for (int i = 0; i < skeleton->m_arrGeo.size(); ++i) {
print out the size = 2;
delete skeleton->m_arrGeo[i]->skeleton_reference;
print out the size = 1;
}
delete skeleton;

可见问题在于 after executing the blue line, one element has been removed from the array. so let take a look at the de-constructor of SkeletonReference.
~SkeletonReference() {
find if the parent (the Geometry_i) is in the m_arrGeo[],
if yes, remove it.
}
Actually, this method makes sense, because when a geometry do not possess a SkeleteReference, there is no need to be recorded in the m_arrGeo[] array.

So, the problem is in the for sentence.
for (int i = 0; i < skeleton->m_arrGeo.size(); ++i) {
// we are iterating a dynamic array.
// we can not make sure that we can visit all the elements.
...
}
change it to:
std::vector<Geometry *> arrGeo = skeleton->m_arrGeo;
for (int i = 0; i < arrGeo.size(); ++i) {
// this is right.
delete arrGeo[i]->skeleton_reference;
}



没有评论:

发表评论