2013-03-13 64 views
0

在我的光線跟蹤器中,我構造了一個包圍體層次結構。我用了幾天的時間試圖解決這個錯誤,但我似乎在做一些根本性的錯誤。與矢量相關的空指針

這第一種方法是被調用的構造是下面的一個使用typedef std :: vector Objects數組。

void BVH::build(Objects* objs) 
{ 
    // construct the bounding volume hierarchy 
    int size = objs->size(); 

    // Calculate the bounding box for this node 
    BBox bb = (*objs)[0]->boundingBox(); 
    for (int p = 1; p < size; p++) 
     bb.expandToInclude((*objs)[p]->boundingBox()); 
    Vector3 pivot = (bb.max + bb.min) * 0.5f; 
    tree.bbox = bb; 

    int split = qsplit(objs, size, pivot.x, 0); 

    tree.left = subdivision(objs, split, 1); 
    tree.right = subdivision(&objs[split], size - split, 1); 
} 

這個方法被下面的一個用來構造我的二叉樹中的葉節點。

Node* BVH::makeLeaf(Objects* objs, int num) 
{ 
    Node* node = new Node; 
    if (num == 1) { node->objs = &objs[0]; } 
    else if (num == 2) { node->objs = ((&objs)[0],(&objs)[1]); } 
    node->isLeaf = true; 
    return node; 
} 

這是一個遞歸方法,使用對象數組來分裂和構造節點和葉節點。

Node* BVH::subdivision(Objects* objs, int size, int axis) 
{ 
    if (size == 1) { return makeLeaf(objs, 1); } 
    if (size == 2) { return makeLeaf(objs, 2); } 

    Node* node = new Node; 
    node->isLeaf = false; 

    BBox bb = (*objs)[0]->boundingBox(); 
    for (int p = 1; p < size; p++) 
     bb.expandToInclude((*objs)[p]->boundingBox()); 
    node->bbox = bb; 
    Vector3 pivot = (bb.max + bb.min) * 0.5f; 

    int split = qsplit(objs, size, pivot[axis], axis); 

    node->left = subdivision(objs, split, (axis + 1) % 3); 
    node->right = subdivision(&objs[split], size - split, (axis + 1) % 3); 

    return node; 
} 

運行此代碼會給我一個細分內的分段錯誤。

下面是空指針從gdb的一個帖子:

debug: Loading "teapot.obj"... 
debug: Loaded "teapot.obj" with 576 triangles 

Program received signal SIGSEGV, Segmentation fault. 
0x000000000040bb9e in BVH::subdivision (this=0x61f0c0, objs=0x61f100, size=5, axis=1) at BVH.cpp:44 
44  BBox bb = (*objs)[0]->boundingBox(); 
(gdb) bt 
0 0x000000000040bb9e in BVH::subdivision (this=0x61f0c0, objs=0x61f100, size=5, axis=1) at BVH.cpp:44 
1 0x000000000040bdef in BVH::subdivision (this=0x61f0c0, objs=0x61f0a0, size=9, axis=0) at BVH.cpp:56 
2 0x000000000040bd62 in BVH::subdivision (this=0x61f0c0, objs=0x61f0a0, size=18, axis=2) at BVH.cpp:53 
3 0x000000000040bd62 in BVH::subdivision (this=0x61f0c0, objs=0x61f0a0, size=36, axis=1) at BVH.cpp:53 
4 0x000000000040bd62 in BVH::subdivision (this=0x61f0c0, objs=0x61f0a0, size=72, axis=0) at BVH.cpp:53 
5 0x000000000040bd62 in BVH::subdivision (this=0x61f0c0, objs=0x61f0a0, size=144, axis=2) at BVH.cpp:53 
6 0x000000000040bd62 in BVH::subdivision (this=0x61f0c0, objs=0x61f0a0, size=288, axis=1) at BVH.cpp:53 
7 0x000000000040b9ca in BVH::build (this=0x61f0c0, objs=0x61f0a0) at BVH.cpp:21 
8 0x00000000004121ac in Scene::preCalc (this=0x61f0a0) at Scene.cpp:42 
9 0x0000000000402fde in makeTeapotScene() at assignment1.cpp:113 
10 0x000000000040f973 in main (argc=1, argv=0x7fffffffe798) at main.cpp:65 
(gdb) p (*objs)[0] 
$1 = (Object *&) @0x0: <error reading variable> 
+0

爲什麼你使用一個*指針*來指向一個'vector',一個'vector'指針,以及爲什麼要合併這兩個指針:)? – us2012 2013-03-13 21:41:46

+0

因爲製作這個框架的人定義了這個構建函數來接收這個矢量,我完全同意它是瘋狂的,但是從來沒有那麼少是我必須處理的。 – miniwolf 2013-03-13 21:43:36

+0

與此同時,它可能是值得使用的valgrind:gdb只捕獲問題,一旦它肯定太遲了,valgrind可能會給你寶貴的信息,如果你意外地訪問數組越界或類似的東西。 – us2012 2013-03-13 21:45:03

回答

2
(&objs)[0] 

相同

*(&objs) 

這是一樣的

objs 

在同方式,

(&objs)[1] 

相同

objs + 1 

這是最有可能的有效對象的地址。

node->objs = ((&objs)[0],(&objs)[1]); 

,因爲它使用逗號運算符,扔掉的(&objs)[0]的值,並將node->objsobjs + 1,這是無效的。

目前還不清楚你期望完成任務,所以我不知道你應該用什麼替換它。

+0

在與我的一位朋友談話後,我用下面的代碼替換了這個gode: node-> objs = new std :: vector ;如果(num == 1) node-> objs-> push_back((* objs)[0]); } else if(num == 2) { node-> objs-> push_back((* objs)[0]); node-> objs-> push_back((* objs)[1]); } – miniwolf 2013-03-13 21:49:13

+0

對此答案+1。 @miniwolf,至少在另一個地方還有同樣的問題:'node-> right = subdivision(&objs [split] ...' – us2012 2013-03-13 21:50:27

0

用很多時間在這個有趣的typedef後,我接到了一個朋友的幫助,我們寫了一個適配器方法打開

vector<Object*>* into vector<Object*>& 

這給了每一個方法的更清潔,外觀漂亮。

void BVH::build(Objects* objs_orig) 
{ 
    m_objects = objs_orig; 
    std::vector<Object*>* objs = objs_orig; 
    return build(*objs); 
} 

void BVH::build(const std::vector<Object*>& objs) 
{ 
    tree = makeTree(objs, 1); 
}