仅Debug模式下创建Vulkan逻辑设备时vkCreateDevice报访问违规错误
问题原因及修复方案
你遇到的Debug模式下vkCreateDevice访问违例问题由以下几个可能的原因导致,按触发概率从高到低排列:
- 队列族数组栈溢出
你先调用vkGetPhysicalDeviceQueueFamilyProperties获取了实际队列族数量queueFamilyCount,但直接使用固定长度为512的栈上数组存储结果,部分特殊硬件/驱动的队列族数量可能超过512,第二次调用该API时会发生栈写越界。Debug模式下会主动检测栈溢出触发异常,Release模式下未做栈溢出检测所以可能侥幸运行。
修复方案:根据实际获取的队列族数量动态分配内存,示例代码如下:uint32_t queueFamilyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount); vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); - 未校验队列族查找结果
你没有判断FindQueueFamilies的返回值就直接使用indices填充设备创建信息,如果当前物理设备没有图形队列族,indices会保留初始值0,传入非法的队列族索引可能触发驱动侧的空指针解引用。
修复方案:调用FindQueueFamilies后先判断返回值,查找失败直接终止创建设备流程。 - 设备扩展参数非法
代码中deviceExtensionsCount和deviceExtensions没有做合法性校验,如果deviceExtensions是野指针、数组内的扩展名字符串不合法(未以\0结尾、为空指针),或者deviceExtensionsCount和数组实际长度不符,驱动读取扩展列表时就会发生访问违例。
修复方案:提前校验扩展列表的合法性,也可以调用vkEnumerateDeviceExtensionProperties确认需要开启的扩展全部支持后再填入创建信息。 - 隐藏的返回值问题
函数末尾return &device;返回了栈上局部变量VkDevice device的地址,函数退出后栈内存会被系统回收,后续访问该指针会出现未定义行为,即使创建设备成功后续也会触发崩溃。
修复方案:将返回值类型改为VkDevice直接返回device的值,或者将device存储在类成员变量中再返回指针。
内容的提问来源于stack exchange,提问作者Deex
相关产品推荐
相关产品推荐

