c++ - 尝试在构造函数中的“glm::cross”初始化我的类段错误
问题描述
我正在编写一个简单的 OpenGL 程序,目前正在开发一个 Camera 类。但是,尝试初始化相机类会导致段错误glm::cross
我试过用两者进行初始化,new
就像Camera(...)
这样:
Camera *c = new Camera(glm::vec3(0, 0, 0), glm::vec2(0, 0), nullptr);
Camera c = Camera(glm::vec3(0, 0, 0), glm::vec2(0, 0), nullptr);
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}
。“十字架之后”永远不会被打印出来。
目前,我很茫然。任何帮助,将不胜感激。
解决方案
我怀疑“无关”方法实际上包含内存损坏错误。我在您发布的代码中没有看到任何明显错误的内容。
内存损坏的工作方式是程序的某些部分覆盖了一些它不应该覆盖的数据,在程序的内存中留下了一点地雷。然后那个地雷随时可能被任何东西击中,不可预知。在您的评论中,您说“glm 函数......没有明显的原因出现段错误”——这是内存损坏问题的常见症状。
为了调试它,首先,我通常会尝试稳定错误:在尝试追踪原因之前确保它可靠地发生,以便在我进行小的更改时它不会溜走。如果您的 C++ 实现(编译器和库)具有“调试堆”,请启用它。 这个答案有许多相关的建议。
在某些情况下,调试堆或类似的东西会自行查明问题。但如果不是,那么一旦你稳定了错误,就开始删除(禁用、注释等)程序的部分,直到找到使错误停止发生的东西。 该代码不一定是问题! 它只是以某种方式参与。将该代码放回原处(因此错误再次出现),并寻找其他要删除的内容。这样做 2-3 次,您将获得 (1) 一个简短的嫌疑人列表,以及 (2) 创建一个具有相同问题的较小程序,从而使整个过程更容易。
我会说继续这样做,直到您找到问题或将程序减少到例如不超过 50 行,这样您就可以在 SO 上发布该代码。这可能看起来很忙,但实际上并非如此。这是一项非常有价值的通用技能。
推荐阅读
- python-3.x - Python中的Deque附加字典与Deque(字典)
- python - 如何使用带有要更改的变量的列表在 for 循环中更改分类变量
- redux - 如何从嵌套对象 redux 状态中删除项目
- android - Rxjava 一次性使用 Fire and Forget API 调用
- javascript - 如何在数据表中更改从数据库中获取的日期格式
- xml - 我想使用变量中的元素内容作为 XPath 值
- python - 如何使用 Django 更新对象并在特定时间创建一个?
- ssl - 什么是 TLS,我们为什么需要它?
- javascript - 为什么当我单击时出现警告框 javascript 中的未定义问题
- java - 为什么这个寻找素数的程序会输出两个答案?