Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用ifstream时OpenGL版本过低_C++_Opengl - Fatal编程技术网

C++ 使用ifstream时OpenGL版本过低

C++ 使用ifstream时OpenGL版本过低,c++,opengl,C++,Opengl,我正在为2D roguelike编写引擎的一些元素。我在一个我希望能够打开的地方。(我手动操作,因为我喜欢了解这些东西。)因此我创建了一个PngLoader类,并开始用它做一些基本的事情,比如。。。打开文件。出于某种原因,这会破坏OpenGLGLFunctionFinder类,该类除了手动之外,还执行类似于GLEW的操作 当OpenGL版本过低时,GLFF基本上会使程序崩溃;这是预期的行为。(可能是一个未设置的函数指针上的segfault。我可以通过使其更优雅地崩溃来“修复”这个问题,但谁在乎呢

我正在为2D roguelike编写引擎的一些元素。我在一个我希望能够打开的地方。(我手动操作,因为我喜欢了解这些东西。)因此我创建了一个
PngLoader
类,并开始用它做一些基本的事情,比如。。。打开文件。出于某种原因,这会破坏OpenGL
GLFunctionFinder
类,该类除了手动之外,还执行类似于GLEW的操作

当OpenGL版本过低时,GLFF基本上会使程序崩溃;这是预期的行为。(可能是一个未设置的函数指针上的segfault。我可以通过使其更优雅地崩溃来“修复”这个问题,但谁在乎呢?)GLFF通常工作得相当好,因为我的图形卡运行OpenGL 4.3左右,但几天前当驱动程序切换到集成图形驱动程序(仅适用于OpenGL 1.1版)时,我确实让它崩溃了。这是通过更改图形仪表板中的某些设置修复的

因此,当我写这样的东西时,我今天突然想到的问题出现了:

class ifcontainerclass {
    std::ifstream fs;
};

/* other code */

int WINAPI WinMain(/* ... */) {
    GLFunctionFinder ff;
    ff.interrogateWindows();

    ifcontainerclass ifcc;

    /* GL code and main loop */

    return 0;
}
。。。OpenGL上下文在版本1.1上卡住了。如果我将
ifstream
更改为
fstream
,我会得到预期的更高版本上下文,问题就会消失

我还在测试中发现,如果我注释掉
GL代码和主循环
区域,问题再次消失。“版本过低”检查是在
GLFunctionFinder::interrogateWindows()
中完成的,而不是在以后的GL代码中完成的,因此仍在检查这些条件。(经过一些测试,我发现注释掉
MSG
结构是问题得以解决的原因。)

我目前的看法是,编译器正在做一些魔术,导致Windows/Intel/NVidia在以下情况下只发出OpenGL 1.1上下文/连接到错误的驱动程序。。。我真的不知道什么时候。这个问题似乎很武断

我可能会考虑去掉我出于懒惰而使用的global
HDC
和global
HGLRC
,因为我认为问题与如何初始化有关/编译器如何安排初始化这些东西,把他们从全球范围内拉出来,我就能更有效地检查和控制这个过程。我在
GLFunctionFinder
中使用了一个
static void*GlobalAddr=this
文件范围的指针,在虚拟窗口的
WndProc
中将其转换为
GLFunctionFinder
,并将
HDC
HGLRC
作为
GLFunctionFinder
的成员变量,可通过指针访问。我可能会在我的主窗口中尝试类似的东西;不管怎样,我一直需要清理全球范围的东西。我可以做的另一件事是在调试器中运行每个版本,并查看它的差异,尽管我不愿意这样做,因为调试在我的IDE中没有正确设置,我也不希望修复它

我想我可以同时使用
fstream
而不是
ifstream
,但我不喜欢不理解这么奇怪的问题,因为它暗示了某种不稳定性,在我有10k行代码任意停止运行之前,我应该意识到这一点,并且只能通过改变其他地方看起来完全不相关的东西来修复

问题:

  • 到底发生了什么事?这里的核心问题是什么
  • 为什么将
    ifstream
    更改为
    fstream
    可以解决问题
  • 为什么注释掉
    MSG
    struct可以解决这个问题
PS:
NvOptimusEnablement=0x00000001
未修复该问题

PPS:MingW4.9.2在Qt中(作为一个IDE,没有Qt库)使用CMake

编辑:在确定将
-ggdb
传递给g++时Qt的调试器工作后,我仔细检查了代码,发现
GLFunctionFinder
中的
PIXELFORMATDESCRIPTOR
没有被分配;我将属性分配给某个随机临时变量而不是成员变量,而
ChoosePixelFormat
使用的是成员变量。由于您获得的上下文取决于您指定的像素类型,因此我实际上是在从Windows请求不确定的设备上下文。编译的细节决定了在
PIXELFORMATDESCRIPTOR
中放入了哪些随机垃圾,而声明
ifstream
而不是
fstream
会在该区域放入错误的随机垃圾

通过在
this->pfd\uu=pfd的效果上添加一些东西,问题得到了解决pfd
后,将code>转换为
GLFunctionFinder
的构造函数

编辑2:为了满足我对“off-topic”标志含义的理解,我将提供一个核心问题的最小示例:

main.cpp:

#include <windows.h>
#include <sstream>
#include <GL/gl.h>

HDC   h_dc;
HGLRC h_context;

LRESULT CALLBACK MainWndProc(_In_ HWND   h_wnd,
                             _In_ UINT   u_msg,
                             _In_ WPARAM w_param,
                             _In_ LPARAM l_param) {
    switch(u_msg) {
    case WM_CREATE: {
        PIXELFORMATDESCRIPTOR pfd; // <-- This was the error source, (pfd not set to an
                                   //     accelerated format, but only sometimes) 
                                   //     except in my code it was harder to see than
                                   //     this.
        h_dc = GetDC(h_wnd);
        int pfint = ChoosePixelFormat(h_dc, &pfd);
        SetPixelFormat(h_dc, pfint, &pfd);
        h_context = wglCreateContext(h_dc);
        wglMakeCurrent(h_dc, h_context);
        const unsigned char * version_string =
                static_cast<const unsigned char *>(glGetString(GL_VERSION));
        if(version_string[0] == '1' || version_string[0] == '2') {
            std::stringstream ss;
            ss << "OpenGL version (" << version_string << ") is too low";
            MessageBox(NULL, ss.str().c_str(), "Error", MB_OK | MB_ICONERROR);
        }
        break;
    }

    case WM_DESTROY:
        PostQuitMessage(EXIT_SUCCESS);
        break;

    default:
        return DefWindowProc(h_wnd, u_msg, w_param, l_param);
    }

    return 1;
}

int WINAPI WinMain(  HINSTANCE h_inst,
                     HINSTANCE h_previnst,
                     LPSTR cmd_str_in,
                     int cmd_show_opt) {

    WNDCLASSEX wc;

    wc.cbSize         = sizeof(WNDCLASSEX);
    wc.style          = CS_OWNDC;
    wc.lpfnWndProc    = MainWndProc;
    wc.cbClsExtra     = 0;
    wc.cbWndExtra     = 0;
    wc.hInstance      = h_inst;
    wc.hIcon          = NULL;
    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground  = (HBRUSH)(COLOR_BACKGROUND + 1);
    wc.lpszMenuName   = NULL;
    wc.lpszClassName  = "MAINWIN";
    wc.hIconSm        = NULL;

    RegisterClassEx(&wc);

    HWND h_wnd = CreateWindowEx(0,
                                "MAINWIN",
                                "MCVE Program",
                                WS_OVERLAPPEDWINDOW,
                                CW_USEDEFAULT,
                                CW_USEDEFAULT,
                                640,
                                480,
                                NULL,
                                NULL,
                                h_inst,
                                NULL);

    return EXIT_SUCCESS;
}

如果有人跳到最后,问题就解决了,但我不知道该如何表示。

因此,我实际看到的是由于默认初始化结构而导致的未定义行为的影响,其中包含的值未初始化:

class GLFunctionFinder {
    PIXELFORMATDESCRIPTOR pfdarr_;
    /* other code */

    GLFunctionFinder();
    setupContext();
    /* other code */
}

GLFunctionFinder::GLFunctionFinder() {
    /* other code */
    PIXELFORMATDESCRIPTOR pfd = { /* things */ };
    // Missing: pfdarr_ = pfd;
    // pfdarr_ never gets set
}

GLFunctionFinder::setupContext() {
    // Undefined behavior:
    int px_format_default = ChoosePixelFormat(this->h_cd, &(this->pfdarr_));
    /* other code */
}
这就给了
ChoosePixelFormat
任何垃圾都在
pfdarr\uu
中。当我最初写这篇文章时,它的表现似乎没有问题,因为垃圾数据“看起来”像是一种加速像素格式类型,
ChoosePixelFormat
会给我一种
int格式,它产生了我所追求的OpenGL上下文。它这样保持了一段时间,因为它一直在工作

fstream
切换到
ifstream
改变了编译器布局/优化程序的一些细节,而
pfdarr\uu
中的垃圾数据更改为“看起来像”一种未加速的格式。这导致获取错误的cont
class GLFunctionFinder {
    PIXELFORMATDESCRIPTOR pfdarr_;
    /* other code */

    GLFunctionFinder();
    setupContext();
    /* other code */
}

GLFunctionFinder::GLFunctionFinder() {
    /* other code */
    PIXELFORMATDESCRIPTOR pfd = { /* things */ };
    // Missing: pfdarr_ = pfd;
    // pfdarr_ never gets set
}

GLFunctionFinder::setupContext() {
    // Undefined behavior:
    int px_format_default = ChoosePixelFormat(this->h_cd, &(this->pfdarr_));
    /* other code */
}