初始化Vulkan Instance时触发读取访问违例问题排查
问题:调用vkCreateInstance触发vulkan-1.dll读取访问违例
调用vkCreateInstance()初始化Vulkan Instance时,触发来自vulkan-1.dll的读取访问违例错误。开发环境为Visual Studio 2022,使用SDL管理窗口,Windows系统与显卡驱动均已更新至最新版本,相关代码如下:
#include <vulkan/vulkan.hpp> #include <SDL.h> #include <SDL_vulkan.h> #include <vector> #include <iostream> SDL_Window* window; int main(int argc, char *argv[]) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cout << "Video initialization failed:" << std::endl; } window = SDL_CreateWindow("vkTest", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN); SDL_vulkanInstance inst; VkInstanceCreateInfo inst_info; VkApplicationInfo appInfo; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "engine"; appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.apiVersion = VK_API_VERSION_1_0; inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; inst_info.pApplicationInfo = &appInfo; inst_info.flags = 0; uint32_t vkExtensionCount = 0; if (!SDL_Vulkan_GetInstanceExtensions(window, &vkExtensionCount, NULL)) { std::cout << "Unable to get Vulkan extensions." << std::endl; exit(EXIT_FAILURE); } std::vector<const char*> vkExtensions; vkExtensions.resize(vkExtensionCount); if (!SDL_Vulkan_GetInstanceExtensions(window, &vkExtensionCount, vkExtensions.data())) { std::cout << "Unable to get Vulkan extensions." << std::endl; exit(EXIT_FAILURE); } std::cout << *vkExtensions.data() << std::endl; inst_info.enabledExtensionCount = vkExtensionCount; inst_info.ppEnabledExtensionNames = vkExtensions.data(); inst_info.enabledLayerCount = 0; VkResult res = vkCreateInstance(&inst_info, nullptr, &inst); if (res == VK_ERROR_INCOMPATIBLE_DRIVER) { std::cout << "Cannot find compadible vulkan driver." << std::endl; exit(EXIT_FAILURE); } else if (res) { std::cout << "unknown error" << std::endl; exit(EXIT_FAILURE); } }
错误原因分析
- 变量类型错误:
SDL_vulkanInstance不是标准Vulkan的VkInstance类型,vkCreateInstance需要传入VkInstance*类型指针,类型不匹配会导致写入非法内存区域,直接触发访问违例。 - 结构体未完全初始化:
VkInstanceCreateInfo的pNext、ppEnabledLayerNames等未使用的指针成员未初始化为nullptr,Vulkan要求所有结构体的未使用指针成员必须显式设为nullptr,否则会引发未定义行为。 - 未定义窗口尺寸宏:
SCREEN_WIDTH和SCREEN_HEIGHT未定义,可能导致SDL窗口创建失败,后续传入无效窗口句柄给SDL_Vulkan_GetInstanceExtensions引发连锁错误。 - 错误处理不完整:
SDL_Init失败后未直接退出,SDL_CreateWindow返回nullptr时未做错误处理,可能导致后续操作使用无效窗口句柄。
修复步骤
- 将
SDL_vulkanInstance inst;改为VkInstance inst = nullptr;,使用标准Vulkan实例类型。 - 显式初始化
VkInstanceCreateInfo的所有未使用成员为nullptr,或用值初始化({})自动清零。 - 定义
SCREEN_WIDTH和SCREEN_HEIGHT的具体值,例如#define SCREEN_WIDTH 800和#define SCREEN_HEIGHT 600。 - 完善错误处理:
SDL_Init失败后直接退出,检查SDL_CreateWindow返回值,确保窗口创建成功。
修正后的代码
#include <vulkan/vulkan.hpp> #include <SDL.h> #include <SDL_vulkan.h> #include <vector> #include <iostream> #define SCREEN_WIDTH 800 #define SCREEN_HEIGHT 600 SDL_Window* window; int main(int argc, char *argv[]) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { std::cout << "Video initialization failed: " << SDL_GetError() << std::endl; exit(EXIT_FAILURE); } window = SDL_CreateWindow("vkTest", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN | SDL_WINDOW_VULKAN); if (!window) { std::cout << "Window creation failed: " << SDL_GetError() << std::endl; exit(EXIT_FAILURE); } VkInstance inst = nullptr; VkInstanceCreateInfo inst_info{}; // 值初始化自动将所有成员设为0/nullptr VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "engine"; appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.apiVersion = VK_API_VERSION_1_0; inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; inst_info.pApplicationInfo = &appInfo; inst_info.flags = 0; uint32_t vkExtensionCount = 0; if (!SDL_Vulkan_GetInstanceExtensions(window, &vkExtensionCount, NULL)) { std::cout << "Unable to get Vulkan extensions: " << SDL_GetError() << std::endl; exit(EXIT_FAILURE); } std::vector<const char*> vkExtensions(vkExtensionCount); if (!SDL_Vulkan_GetInstanceExtensions(window, &vkExtensionCount, vkExtensions.data())) { std::cout << "Unable to get Vulkan extensions: " << SDL_GetError() << std::endl; exit(EXIT_FAILURE); } inst_info.enabledExtensionCount = vkExtensionCount; inst_info.ppEnabledExtensionNames = vkExtensions.data(); inst_info.enabledLayerCount = 0; inst_info.ppEnabledLayerNames = nullptr; // 显式设为nullptr VkResult res = vkCreateInstance(&inst_info, nullptr, &inst); if (res == VK_ERROR_INCOMPATIBLE_DRIVER) { std::cout << "Cannot find compatible vulkan driver." << std::endl; exit(EXIT_FAILURE); } else if (res != VK_SUCCESS) { std::cout << "Unknown error, result code: " << res << std::endl; exit(EXIT_FAILURE); } // 销毁Vulkan实例 if (inst != nullptr) { vkDestroyInstance(inst, nullptr); } SDL_DestroyWindow(window); SDL_Quit(); return 0; }
内容的提问来源于stack exchange,提问作者bub1401
相关产品推荐
相关产品推荐

