首页 > 解决方案 > 尝试在构造函数中的“glm::cross”初始化我的类段错误

问题描述

我正在编写一个简单的 OpenGL 程序,目前正在开发一个 Camera 类。但是,尝试初始化相机类会导致段错误glm::cross

我试过用两者进行初始化,new就像Camera(...)这样:

  1. Camera *c = new Camera(glm::vec3(0, 0, 0), glm::vec2(0, 0), nullptr);
  2. Camera c = Camera(glm::vec3(0, 0, 0), glm::vec2(0, 0), nullptr);
  3. Camera c(glm::vec3(0, 0, 0), glm::vec2(0, 0), nullptr);

但是,它们三个都产生相同的结果。(nullptr作为 arg 与它无关,因为它只是被分配给一个属性)

我的相机课:

class Camera {
    public:
        glm::vec3 up;
        glm::vec3 right;
        glm::vec3 forward;

        glm::vec3 lookDirection;
        glm::vec3 position;

        float fov = 70, near = 0.1f, far = 100.0f;

        glm::vec2 lookAngle;
        GLFWwindow *win;

        Camera(glm::vec3 pos, glm::vec2 look, GLFWwindow *window) {
            win = window;
            lookAngle = look;
            position = pos;

            lookDirection = glm::vec3(cos(lookAngle.y) * sin(lookAngle.x), sin(lookAngle.y),
                                  cos(lookAngle.y) * cos(lookAngle.x));

            right = glm::vec3(sin(lookAngle.x - pi / 2.0f), 0, cos(lookAngle.x - pi / 2.0f));
            forward = glm::vec3(sin(lookAngle.x), 0, cos(lookAngle.x));
            // I would print `right` and `lookDirection` here.
            up = glm::cross(right, lookDirection);
            std::cout << "After cross" << std::endl;
        }

        ...  // Some irrelevant methods
}

但是,在 上up = glm::cross(right, lookDirection);,它会出现段错误

glm::detail::compute_cross<float, (glm::qualifier)0, false>::call(glm::vec<3, float, (glm::qualifier)0> const&, glm::vec<3, float, (glm::qualifier)0> const&):
    pushq  %rbp
    movq   %rsp, %rbp
    subq   $0x20, %rsp
    movq   %rdi, %rax
    movq   %rsi, -0x8(%rbp)
    movq   %rdx, -0x10(%rbp)
    movq   -0x8(%rbp), %rdx
    movss  0x4(%rdx), %xmm0           # xmm0 = mem[0],zero,zero,zero
    movq   -0x10(%rbp), %rdx
    mulss  0x8(%rdx), %xmm0      # <------- IT WOULD SEGFAULT RIGHT HERE
    movq   -0x10(%rbp), %rdx
    movss  0x4(%rdx), %xmm1           # xmm1 = mem[0],zero,zero,zero
    movq   -0x8(%rbp), %rdx

right将 等于 {-1, 0, 6.12323e-17}lookDirection将 等于{0, 0, 1}。“十字架之后”永远不会被打印出来。

目前,我很茫然。任何帮助,将不胜感激。

标签: c++segmentation-faultglm-math

解决方案


我怀疑“无关”方法实际上包含内存损坏错误。我在您发布的代码中没有看到任何明显错误的内容。

内存损坏的工作方式是程序的某些部分覆盖了一些它不应该覆盖的数据,在程序的内存中留下了一点地雷。然后那个地雷随时可能被任何东西击中,不可预知。在您的评论中,您说“glm 函数......没有明显的原因出现段错误”——这是内存损坏问题的常见症状。

为了调试它,首先,我通常会尝试稳定错误:在尝试追踪原因之前确保它可靠地发生,以便在我进行小的更改时它不会溜走。如果您的 C++ 实现(编译器和库)具有“调试堆”,请启用它。 这个答案有许多相关的建议。

在某些情况下,调试堆或类似的东西会自行查明问题。但如果不是,那么一旦你稳定了错误,就开始删除(禁用、注释等)程序的部分,直到找到使错误停止发生的东西。 该代码不一定是问题! 它只是以某种方式参与。将该代码放回原处(因此错误再次出现),并寻找其他要删除的内容。这样做 2-3 次,您将获得 (1) 一个简短的嫌疑人列表,以及 (2) 创建一个具有相同问题的较小程序,从而使整个过程更容易。

我会说继续这样做,直到您找到问题或将程序减少到例如不超过 50 行,这样您就可以在 SO 上发布该代码。这可能看起来很忙,但实际上并非如此。这是一项非常有价值的通用技能。


推荐阅读