【问题标题】:NULL-pointer associated with vector与向量关联的 NULL 指针
【发布时间】:2013-03-14 09:43:04
【问题描述】:

在我的光线追踪器中,我正在构建一个包围体层次结构。我花了几天时间试图修复这个错误,但我似乎在做一些根本错误的事情。

第一种方法是被调用的构造,下面是使用 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;
}

这是一种递归方法,使用Objects数组来拆分和构造节点和叶子节点。

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>

【问题讨论】:

  • 你为什么要使用一个 pointer 指向 vector 和一个 vector 来保存指针,你为什么要把这两者结合起来:)?
  • 因为制作框架的人定义了这个构建函数来接收这个向量,我完全同意这很疯狂,但我必须处理的事情永远不会少。
  • 与此同时,使用 valgrind 可能是值得的:gdb 仅在绝对为时已晚时才发现问题,如果您不小心访问超出范围的数组或类似的事情,valgrind 可能会为您提供有价值的信息。

标签: c++ segmentation-fault bounding-volume


【解决方案1】:
(&objs)[0]

一样
*(&objs)

相同
objs

同理,

(&objs)[1]

相同
objs + 1

这很可能不是有效对象的地址。

线

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

由于使用了逗号运算符,所以将(&amp;objs)[0]的值扔掉,将node-&gt;objs设置为objs + 1,无效。

不清楚你期望这个任务完成什么,所以我不知道你应该用什么替换它。

【讨论】:

  • 与我的朋友交谈后,我将那块神器替换为: node->objs = new std::vector; if ( num == 1 ) 节点->objs->push_back((*objs)[0]); } else if ( num == 2 ) { node->objs->push_back((*objs)[0]);节点->objs->push_back((*objs)[1]); }
  • 这个答案+1。 @miniwolf,你至少还有一个地方有同样的问题:node-&gt;right = subdivision(&amp;objs[split]...
【解决方案2】:

在这个有趣的 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);
}

【讨论】:

    猜你喜欢
    • 2011-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-22
    • 2014-02-23
    • 2010-12-19
    • 1970-01-01
    相关资源
    最近更新 更多