You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下GLFW创建Vulkan Surface报错 GLFW_NO_API设置未生效

根本原因

你遇到的Surface创建报错、关闭事件响应异常都不是GLFW本身的缺陷,是代码里的3个逻辑错误导致的:

  • 核心错误:initWindow函数的窗口参数为值传递,有效窗口指针丢失
    C++中形参GLFWwindow *window是函数内的局部副本,你在函数内给window赋值glfwCreateWindow返回值时,仅修改了局部变量,不会改变外部app->window的值。你调用glfwWindowHint设置的GLFW_NO_API属性确实生效了,但配置正确的窗口指针只存在于initWindow的局部作用域,函数返回后就丢失了。后续所有操作拿到的app->window是未初始化的野指针,GLFW检测到传入的非法窗口对象没有配置NO_API,就会抛出65540错误,glfwWindowShouldClose无法正常工作也是同一个原因。
  • 验证层检测逻辑写反
    checkValidationLayerSupport函数中对strcmp的返回值判断错误:strcmp返回0代表两个字符串完全相等,你当前的写法是字符串不相等时才标记层为已找到,完全颠倒了判断逻辑,会导致验证层检测结果异常。
  • 资源清理顺序错误
    现有清理逻辑先销毁GLFW窗口、终止GLFW,再销毁Vulkan Surface,而Vulkan Surface是依赖GLFW窗口创建的资源,逆序销毁会触发资源泄漏或运行时错误。
修复方法

按以下步骤修改代码即可解决所有问题:

  1. 修改initWindow的参数传递逻辑,保证窗口指针正确写回Application结构体
    把initWindow的形参从GLFWwindow *window改为Application *app,直接在函数内给app的window成员赋值:
static void initWindow(Application *app) {
    glfwInit();
    
    glfwSetErrorCallback(glfwErrorCallback);

    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

    app->window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Vulkan", nullptr, nullptr);
    if (app->window == NULL) {
        throw std::runtime_error("Failed to create window!\n");
    }
    printf("Created window.\n");

    glfwSetWindowCloseCallback(app->window, windowCloseCallback);
    glfwSetKeyCallback(app->window, keyCallback);

    RUNNING = true;
}

对应修改runApplication中的调用为initWindow(app);即可。

  1. 修正验证层匹配逻辑
    把checkValidationLayerSupport中的strcmp判断改为相等时才标记找到:
for (const auto &layer_properties : available_layers) {
    // strcmp返回0代表字符串相等
    if (strcmp(layer_name, layer_properties.layerName) == 0) {
        found = true;
        break;
    }
}
  1. 调整资源清理顺序
    先销毁所有Vulkan资源,再销毁GLFW窗口、终止GLFW,修改cleanUp函数:
static void cleanUp(Application *app) {
    printf("Cleaning up!\n");
    // 先销毁Vulkan相关资源
    vkDestroySurfaceKHR(app->vk_instance, app->vk_surface, nullptr);
    vkDestroyDevice(app->vk_device, nullptr);
    vkDestroyInstance(app->vk_instance, nullptr);
    // 再销毁GLFW资源
    glfwDestroyWindow(app->window);
    glfwTerminate();
}

对应修改runApplication中的cleanUp调用为cleanUp(app);。

修复完成后,你之前用来绕过关闭事件问题的全局RUNNING变量可以正常工作,也可以直接删除该全局变量,在主循环中直接用glfwWindowShouldClose(app->window)作为循环判断条件,不需要额外的变通方案。

内容的提问来源于stack exchange,提问作者Mr. Vermeer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 17:45:37