opengl 调用glfwSwapBuffers时出现段错误

0aydgbwb  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(229)

看起来我在ArchLinux,DWM(完全更新和修补)上使用GLFW和OpenGL时出现了seg故障。
我追溯了代码,它在glfwSwapBuffers(window)中有segFault。
下面是我的代码:
main.cpp

#include <iostream>
#include "gui/window.h"

int main(int, char**) {
    Window window("Test GL", 800, 600);

    if(!window.hasCorrectlyLoaded()) {
        return 1;
    }

    while (!window.shouldClose())
    {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        window.pollEvents();
    }
}

window.h

#ifndef __WINDOW_H__
#define __WINDOW_H__

#include <string>
#include <glad/gl.h>
#include <GLFW/glfw3.h>

class Window {
private:
    GLFWwindow *window;
    bool correctlyLoaded;

public:
    Window(const std::string&, int, int);
    ~Window();

    const bool hasCorrectlyLoaded();
    const bool shouldClose();

    const void pollEvents();
};

#endif // __WINDOW_H__

window.cpp

#include "window.h"
#include <spdlog/spdlog.h>

Window::Window(const std::string& title, int width, int height)
{
    correctlyLoaded = false;
    if(!glfwInit()) {
        spdlog::default_logger()->critical("Could not load GLFW");
        return;
    }

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);

    GLFWwindow* window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
    if (!window)
    {
        spdlog::default_logger()->critical("Failed to create GLFW window !");
        return;
    }

    glfwMakeContextCurrent(window);

    if (!gladLoadGL(glfwGetProcAddress))
    {
        spdlog::default_logger()->critical("Failed to load OpenGL !");
        return;
    }

    spdlog::default_logger()->info("Loaded OpenGL {}", glfwGetVersionString());
    
    glViewport(0, 0, width, height);
    correctlyLoaded = true;
}

const void Window::pollEvents()
{
    glfwSwapBuffers(window);
    glfwPollEvents(); //<- Seg fault here
}

Window::~Window()
{
    glfwTerminate();
}

const bool Window::hasCorrectlyLoaded()
{
    return correctlyLoaded;
}

const bool Window::shouldClose()
{
    return glfwWindowShouldClose(window);
}

在进一步研究时,我偶然发现了一个答案,它告诉我设置glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API)窗口提示,但我仍然得到了一个segfault,但在不同的位置:
GLFW源代码

GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
{
    _GLFWwindow* window = (_GLFWwindow*) handle;
    assert(window != NULL);

    _GLFW_REQUIRE_INIT();

    if (window->context.client == GLFW_NO_API)
    {
        _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
                        "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context"); //<- Seg fault without window hint
        return;
    }

    window->context.swapBuffers(window); //<- Seg fault with window hint
}

下面是我从日志记录中得到的输出:

[2022-05-24 20:01:04.252] [info] Loaded OpenGL 3.4.0 X11 GLX Null EGL OSMesa monotonic
[1]    432406 segmentation fault (core dumped)  /home/lygaen/code/testgl/build/testgl
l3zydbqr

l3zydbqr1#

您的问题出现在Window.cpp的以下行中:

//...
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);

GLFWwindow* window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); //<---
if (!window)
{
//...

您已经将window重新声明为该构造函数的局部变量,因此,指针永远不会转义该构造函数,而是处于悬挂状态。
当尝试分配类成员时,一个好习惯是使用this关键字。它通常是多余的,但它确实有助于指示意图。因此代码应该改为:

//...
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);

this->window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr); //<---
if (!this->window)
{
//...

如果您的样式准则不允许这样做,您可以省略this->;唯一重要的部分是您没有声明一个完全新的变量来隐藏类成员。

相关问题