尝试在构造函数的 `glm::cross` 处初始化我的 class 段错误

Trying to initialize my class segfaults at `glm::cross` in constructor

我正在编写一个简单的 OpenGL 程序,目前正在研究相机 class。但是,尝试初始化相机 class 会在 glm::cross

处导致段错误

我试过使用 newCamera(...) 进行初始化,如下所示:

  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);

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

我的相机class:

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   [=12=]x20, %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}。 "After cross" 永远不会被打印出来。

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

我怀疑 "irrelevant" 方法实际上包含内存损坏错误。我在您 post 编辑的代码中没有看到明显错误的地方。

内存损坏的工作方式是程序的某些部分覆盖了一些它不应该覆盖的数据,在程序的内存中留下了一点地雷。那么那个地雷随时都可能被任何东西击中,出乎意料。在您的评论中,您说 "glm functions ... are segfaulting for no apparent reason"--这是内存损坏问题的常见症状。

要调试它,首先,我通常会尝试 稳定 错误:确保它可靠地发生,然后再尝试追查原因,以免它溜走当我进行小改动时。如果您的 C++ 实现(编译器和库)有 "debug heap",请启用它。 This answer 有一些相关的建议。

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

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

好的,我找到问题了。它与我发布的代码无关,但与我构建应用程序的方式有关。在我的 CMakeLists.txt 中是 target_link_libraries 中的 glm_shared.dylib。这不知何故混淆了 glm 函数并从 cmake 中删除该行修复了所有问题。