【问题标题】:C++ program changing behavior with different CompilerC++ 程序使用不同的编译器改变行为
【发布时间】:2020-10-18 14:48:02
【问题描述】:

我有一个问题,我的程序正在改变它的行为,这取决于它是否是从调试器启动的。二进制文件是一样的!我的问题是通过以下两种方式启动程序:

gdb game vs game(游戏是可执行文件。如果您在 Windows 上,则为 game.exe)

如果附加了调试器,我的程序将按预期工作。您应该在窗口中间看到一个 Square,它将打开。当您移动 Square(wasd/箭头键)时,您会看到,实际上有两个正方形堆叠在一起。

当程序在没有调试器的情况下启动时,第二个“固定”方块不存在。

程序代码:https://github.com/C0D3-M4513R/OpenGLGame/tree/development

问题是,在 applyMVP 调用中的 Shader.cpp 下,提供的 Matrix 其内容发生了变化,从 c++(就在对 OpenGL 的方法调用之前)到 OpenGL(方法调用,改变了 OpenGL 状态)

void Shader::applyMVP(glm::mat4 model) const {
    //TODO::Projection Matrix
//    glm::mat4 mvp = Renderer::getCamera()->view() * model;
    glm::mat4 mvp = model;
    const float* mvpPointer = glm::value_ptr(mvp);

#ifndef DEBUG
    for(unsigned int i = 0; i < 16; i++){
        SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM,"MVP Matrix[%u]: %f",i,mvpPointer[i]);
    }
#endif


    glUseProgram(program);
    GLuint MatrixID = glGetUniformLocation(program, "mvp");
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, mvpPointer);

    glUseProgram(0);
}

在我的代码中一切都很好,但在 OpenGL 中,glUniformMatrix4fv() 调用突然具有非常奇怪的值。我从未提供过的价值观!

如果你想自己编译这个项目,你需要以下:

  • SDL2 库和头文件
  • GLEW 库和头文件
  • 一个(工作的)cmake 环境

如果您运行的是 Linux 或 Windows,则无关紧要,因为程序和编译都适用于两者。

编辑: 在 Windows(使用 MINGW)上,问题与描述的完全一样,但在 Linux(使用 GCC)上,一切正常。所以我猜,MINGW 是问题所在?

一旦使用 MINGW 解决了问题,我将问题标记为完成。

【问题讨论】:

  • 通常这意味着你在某个地方有 UB。确保您启用了警告并且没有收到任何警告,尝试使用 address&UB sanitizers 运行,尝试-D_GLIBCXX_DEBUG,尝试 valgrind 等。
  • 我正在使用标志 -Wall 进行编译。我得到的唯一警告是 -Wreorder 警告。
  • 我也会添加-Wextra
  • 使用 -Wextra 和 -D_GLIBCXX_DEBUG 我还获得以下类型:-Wignored-qualifiers 和 -Wunused-parameter(仅在 main 上)。但问题仍然存在。我正在通过 CMake 设置标志。我这样做对吗? set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Og -g -Wall -Wextra -D_GLIBCXX_DEBUG")
  • @C0D3M4513R -Wall 无法告诉您每种 UB。您描述的问题是指针别名问题。我假设您正在使用 x86 CPU,因此内存访问顺序问题不应该蔓延。无论如何,在获取指针和将其提交给 OpenGL “某事”之间的某个地方发生了。几乎就像mvp 超出范围(它没有)。

标签: c++ opengl mingw glm-math glew


【解决方案1】:

Face 类中的属性glm::mat4x4 rotation; 未初始化。

glm API documentation 指的是The OpenGL Shading Language specification

5.4.2 向量和矩阵构造函数

如果向量构造函数有一个标量参数,它用于将构造向量的所有组件初始化为该标量的值。如果矩阵构造函数只有一个标量参数,则用于初始化矩阵对角线上的所有分量,其余分量初始化为 0.0。

这意味着,单位矩阵可以由单个参数 1.0 初始化:

glm::mat4 rotation = glm::mat4(1.0f); 

【讨论】:

  • 感谢您的来信。我修复了一堆这些东西,但这并不重要,因为我现在实际上并没有使用旋转变量(读数)。也可能是,你可以初始化一个矩阵,就像你描述的那样,但在我的上下文(一个头文件)中,它不起作用,因为它会声明一个函数。
【解决方案2】:

有时不同的编译器的行为会有所不同。请务必尝试使用其他 IDE 来调查问题是否仍然存在。

【讨论】:

  • 好的,谢谢,但现在我很困惑。在我在 Windows 上使用 MINGW 进行编译之前。我现在在 Linux 下使用 GCC 进行了尝试,一切正常。在这种情况下,我应该注意哪些区别?还是我必须处理的只是一些怪癖?如果是这样的话,我该如何处理这个怪癖,以确保我可以支持尽可能多的平台?
  • Windows 和 Linux 是非常不同的操作系统,您需要阅读它们各自的文档。当然,也请阅读a textbook about operating systems
猜你喜欢
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 2021-05-03
  • 2019-01-20
  • 2011-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多