首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >为什么push_back会产生分割错误?

为什么push_back会产生分割错误?
EN

Stack Overflow用户
提问于 2020-05-06 17:20:11
回答 2查看 190关注 0票数 0

关于该项目的

我正在开发一个Opengl射线追踪器,它能够加载obj文件并跟踪它。我的应用程序用assimp加载obj文件,然后使用着色器存储对象将所有三角形面(顶点和索引)发送到片段着色器。基本结构即将呈现结果从碎片着色器到一个四边形。

当我加载更大的obj-s (超过100个三角形)时,计算机需要很长时间才能完成交叉操作,所以我开始创建一个BVH树来加速这个过程。我的BVH根据AABB中包含的三角形的平均中值递归地将空间分割成两个轴对齐包围框。

我成功地构建了BVH树结构(在CPU上),现在我想把它转换成一个简单的数组,然后将它发送到片段着色器(到一个着色器存储缓冲区)。

下面是负责将BVH根节点转换为数组的方法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BvhNode bvhNode; //global variable

BvhNode* putNodeIntoArray() {

    int size=bvhNode.getNumberOfNodes();
    BvhNode nodesArray[size];

    int current_index = 0;
    vector<BvhNode> tempNodes;

    tempNodes.push_back(bvhNode);
    BvhNode current_node;

    while (!tempNodes.empty()) {
        current_node = tempNodes.at(0);

        tempNodes.erase(tempNodes.begin());
        nodesArray[current_index] = current_node;

        if(!current_node.isLeaf)
        {
            tempNodes.push_back(current_node.children.at(0)); // Segmentation error occurs here!
            tempNodes.push_back(current_node.children.at(1));
        }

        current_index++;
    }

    return nodesArray;
}

关于问题的

我不知道为什么,但是当我想要push_back tempNodes向量的第一个子向量时,它会给我一个分割错误(上面的注释可以看到确切的位置)。在我看来,current_node.children.at(0)似乎不存在,但实际上它是根据调试器存在的。我试图编写reference (&)操作符:tempNodes.push_back(&current_node.children.at(0));,但在本例中,它给出了对象的奇怪坐标。我试图将函数中的变量定义为全局变量- -试图避免-的作用域问题,并将current_node变量定义为指针。不幸的是,他们都没有给我更好的结果。

这是我的BvhNode类,如果有帮助的话:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class BvhNode {

public:
    BBox bBox;
    int depthOfNode;
    vector<BvhNode> children;
    int order;
    bool isLeaf;
    bool createdEmpty = false;
    vector<glm::vec3> primitiveCoordinates;

    BvhNode() {}
    BvhNode(BvhNode *pNode) {}

    BvhNode(vector<glm::vec3> &primitiveCoordinates) {
        this->primitiveCoordinates = primitiveCoordinates; }

    void buildTree(vector<glm::vec3>& indicesPerFaces, int depth) {... }

更新1:

我根据评论更新了方法。因此,我将返回值的类型更改为BvhNode*的向量。该算法工作良好,直到到达将叶节点放入std::向量的过程。所以当它开始把图的最后一层放到向量上时,它给了我一个错误:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Program received signal SIGSEGV, Segmentation fault.
0x00007fbda4d69c01 in __GI___libc_free (mem=0x555be3a9dba0) at malloc.c:3123
3123    malloc.c: No such file or directory.

我设法将七个节点(除了树叶级别之外的树的所有深度级别)放入向量中。我也试着运行valgring,但实际上valgring并没有给我任何错误,不像在CLion中那样。

这是我改进的方法。我对分割错误的位置和修复进行了评论。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    BvhNode bvhNode;

    vector<BvhNode> putNodeIntoArray() {

        int size=bvhNode.getNumberOfNodes();

    // FIX:  I modified the array into an std::vector
        vector<BvhNode> nodesArray(size);  

        int current_index = 0;
        vector<BvhNode> tempNodes;

        tempNodes.push_back(bvhNode);   
        BvhNode current_node;

        while (!tempNodes.empty()) {
            current_node = tempNodes.front();// Segmentation error!!
            tempNodes.erase(tempNodes.begin());

            nodesArray.at(current_index)=current_node;
            nodesArray.at(current_index).children.clear();


// FIX: I also modified this not to iterate through leaves' children, because they don't exist.
            if(!current_node.children.empty())  
            {
                tempNodes.push_back(current_node.children.at(0));
                tempNodes.push_back(current_node.children.at(1));
            }
            current_index++;
        }
        return nodesArray;
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-05-09 04:57:32

实际上问题是在创建Bvh树的过程中。因为我想以2*i+1和2*i+2的形式到达子节点,所以我使用了一种方法来填充二叉树(每个级别都有最大的节点数)。在这种方法中,我不得不将空节点推到树上。

我创建了这样的空节点:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BvhNode emptyNode;

而不是这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
BvhNode *emptyNode = new BvhNode();

因此,当方法完成时,emptyNode的生存期就结束了。这就导致了分割错误。

此外,还有一个问题,正如Balá所指出的,在创建平坦的二叉树期间,我按值存储了BvhNode。这个选项使得应用程序速度慢得多,也是另一个可能导致分割错误的地方。

票数 0
EN

Stack Overflow用户

发布于 2020-05-07 13:05:16

您的向量按值在任何地方存储BvhNodes。这意味着每次您push_back一个节点时,都会调用它的复制构造函数,该构造函数依次在节点内复制children向量成员,该成员复制自己的元素等等。这基本上会导致每次插入或删除节点时都复制/释放完整的子树。

这反过来会导致内存碎片,这最终会导致向量重新分配失败并导致分段错误。

如果没有完整的代码,我可以推荐以下两点:

  1. 将子节点存储为(智能)指针,而不是通过值
  2. 为向量创建自定义分配器,以启用更细粒度的调试,并检查分配失败

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61648217

复制
相关文章
为什么HashMap会产生死循环?
HashMap死循环是一个比较常见、也是比较经典的面试题,在大厂的面试中也经常被问到。HashMap的死循环问题只在JDK1.7版本中会出现,主要是HashMap自身的工作机制,再加上并发操作,从而导致出现死循环。JDK1.8以后,官方彻底解决了这个问题。
Tom弹架构
2022/08/22
1.5K0
为什么HashMap会产生死循环?
Elasticsearch 为什么会产生文档版本冲突?如何避免?
模拟脚本2:循环update_by_query 批量更新数据 update.sh。
铭毅天下
2022/09/26
4.1K0
Elasticsearch 为什么会产生文档版本冲突?如何避免?
L1正则为什么会产生稀疏解
在机器学习中,当模型过于复杂时,为了防止产生过拟合的现象,最常用的方法时采用正则化,如L1正则和L2正则.
JNJYan
2019/01/18
1.9K0
前端测试题:(解析)以下哪条语句会产生运行错误?
Number、String、Boolean、undefined、object、Null。
舒克
2021/03/16
9850
前端测试题:(解析)以下哪条语句会产生运行错误?
日更系列:STD容器的push_back为什么会比[]慢
最近在分析算子的火焰图数据,发现了比较多的std::vector::push_back操作,想着这里是否也可以优化一把。
mariolu
2021/12/26
1.1K0
哪些场景会产生OOM?怎么解决?
什么时候会抛出OutOfMemery异常呢?初看好像挺简单的,其实深究起来考察的是对整个JVM的了解,而这个问题从网上可以翻到一些乱七八糟的答案,其实在总结下来基本上4个场景可以概括下来。
MickyInvQ
2023/03/10
2400
哪些场景会产生OOM?怎么解决?
哪些场景会产生OOM?怎么解决?
这个面试题是一个朋友在面试的时候碰到的,什么时候会抛出OutOfMemery异常呢?初看好像挺简单的,其实深究起来考察的是对整个JVM的了解,而且这个问题从网上可以翻到一些乱七八糟的答案,其实在总结下来基本上4个场景可以概括下来。
Java技术栈
2020/10/27
8770
哪些场景会产生OOM?怎么解决?
ChatGPT会产生自我意识吗
在人工智能领域,自我意识是个很重要的话题,哪怕不是人工智能的终极目标,至少也是重要目标。但是,很难。现阶段我们连意识如何运作都还一头雾水,再谈人工触发只能是一本正经地瞎想。
木羊
2023/09/09
2160
语义分割新SOTA | 当UNet与HRNet碰撞会产生怎样的火花?U-HRNet不做选择!!!
密集的预测任务,包括语义分割和深度估计等,是视觉理解系统的重要组成部分。密集预测任务需要预测像素级类别标签或回归特定值,这比图像级预测任务更具挑战性。同时保持高分辨率和强语义信息是有效处理密集预测任务的关键。高分辨率可确保最终预测粒度尽可能接近像素级别,并可获得更精确的局部判别,例如更精确的边缘。强大的语义信息确保了整体预测的准确性,特别是对于难以区分或面积较大的实例。
AiCharm
2023/05/15
6740
语义分割新SOTA | 当UNet与HRNet碰撞会产生怎样的火花?U-HRNet不做选择!!!
EasyPlayer-RTSP播放器集成后为什么会产生大量DUMP文件?如何去除?
很多用户都在我们github上下载EasyPlayer系列的播放器进行集成测试,和大家了解的一样,EasyPlayer系列具有高可用性和适配性,也都具备丰富的二次接口,支持二次开发。很多用户通过EasyPlayer-RTSP播放器编译集成后,系统经常会莫名其妙的产生一堆DUMP文件,如下图:
TSINGSEE青犀视频
2021/09/07
5520
使用C++ Builder 6编译产生错误
作者:Gandalf1024 链接:https://www.jianshu.com/p/f42d045d5014 來源:简书 简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
战神伽罗
2019/07/24
1.1K0
会声会影X5错误
作者:matrix 被围观: 3,013 次 发布时间:2013-06-13 分类:兼容并蓄 | 无评论 »
HHTjim 部落格
2022/09/26
4300
会声会影X5错误
push_back 与 emplace_back
emplace_back 能就地通过参数构造对象,不需要拷贝或者移动内存,相比 push_back 能更好地避免内存的拷贝与移动,使容器插入元素的性能得到进一步提升。在大多数情况下应该优先使用 emplace_back 来代替 push_back。
ClearSeve
2022/02/10
9200
非阻塞情况下connect产生EINPROGRESS错误[通俗易懂]
//原文地址:http://blog.csdn.net/saspss/article/details/8487678
全栈程序员站长
2022/09/09
1.3K0
为什么AngularJs会火?
Angular.js is a MV* (Model – View – Whatever) Javascript framework which is maintained by Google which excels in the creation of single-page-applications or even for adding some “magic” to our classic web applications.
javascript.shop
2019/09/04
9000
为什么@Conditional会失效?
一、背景描述二、常见条件注解失效场景三、聊一聊条件注解实现原理四、问题定位五、解决方案六、参考
叔牙
2023/08/09
6640
为什么@Conditional会失效?
错误使用 C++ 模板特化产生的坑
答案是:链接方式 1 产生的 main 输出 specialization,链接方式 2 产生的 main 输出 normal。
zhiruili
2023/10/20
4370
为什么 demangle 会失败?
本周有位网友在交流群提到“为什么无法在自己的电脑中通过 c++filt 解析符号 _ZN5folly6detail15str_to_integralIxEENS_8ExpectedIT_NS_14ConversionCodeEEEPNS_5RangeIPKcEE ?”
酷酷的哀殿
2020/10/26
1.2K0
为什么 demangle 会失败?
为什么 Google 会很强?
资本总是想榨干员工和机器的每一点剩余价值。如果那一天服务器有了意识,一定会揭竿起义。
LIYI
2022/11/18
6450
点击加载更多

相似问题

为什么这个代码会产生分割错误

210

为什么这个程序会产生分割错误?

20

为什么这个程序会产生分割错误?

20

为什么这个循环(C)会产生分割错误?

20

迭代argv[]会产生分割错误

45
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文