c - Vulkan vkCreateInstance - 访问冲突写入位置 0x0000000000000000
问题描述
我正在尝试使用 Vulkan 编写一个基本程序,但我不断收到运行时错误。
Exception thrown at 0x00007FFDC27A8DBE (vulkan-1.dll) in VulkanTest.exe: 0xC0000005: Access violation writing location 0x0000000000000000.
这似乎是一个相对常见的问题,原因是未能初始化 vkCreateInstance 函数的参数。我已经尝试了我发现向其他人提出的所有解决方案,甚至初始化了我相当确定我不需要的东西,但我仍然无法解决问题。该程序是使用 MSVC 编译器用 C 语言编写的。
#include "stdio.h"
#include "SDL.h"
#include "vulkan\vulkan.h"
#include "System.h"
int main(int argc, char *argv[])
{
//Initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
printf("Error");
}
printf("Success");
//Initialize Vulkan
VkInstance VulkanInstance;
VkApplicationInfo VulkanApplicationInfo;
VulkanApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
VulkanApplicationInfo.pNext = 0;
VulkanApplicationInfo.pApplicationName = "VulkanTest";
VulkanApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
VulkanApplicationInfo.pEngineName = "VulkanTest";
VulkanApplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
VulkanApplicationInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo VulkanCreateInfo = {0,0,0,0,0,0,0,0};
VulkanCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
VulkanCreateInfo.pNext = 0;
VulkanCreateInfo.pApplicationInfo = &VulkanApplicationInfo;
VulkanCreateInfo.enabledLayerCount = 1;
VulkanCreateInfo.ppEnabledLayerNames = "VK_LAYER_KHRONOS_validation";
vkEnumerateInstanceExtensionProperties(0, VulkanCreateInfo.enabledExtensionCount,
VulkanCreateInfo.ppEnabledExtensionNames);
//Create Vulkan Instance
if(vkCreateInstance(&VulkanCreateInfo, 0, &VulkanInstance) != VK_SUCCESS)
{
printf("Vulkan instance was not created");
}
//Create SDL Window
SDL_Window* window;
window = SDL_CreateWindow("VulkanTest", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_VULKAN || SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_Delay(10000);
return 0;
}
解决方案
你确定调用vkCreateInstance()
是什么崩溃了吗?我没有尝试调试您显示的代码(那是您的工作),但只是查看代码正在进行的调用,它应该vkEnumerateInstanceExtensionProperties()
是崩溃的调用(如果它甚至可以编译!)。
的第二个参数vkEnumerateInstanceExtensionProperties()
需要一个uint32_t*
指针,但您传入的uint32_t
值 ( VulkanCreateInfo.enabledExtensionCount
) 已初始化为 0。因此,这将使pPropertyCount
参数成为 NULL 指针(如果它甚至可以编译)。
您正在传递VulkanCreateInfo.ppEnabledExtensionNames
第三个参数(如果它甚至可以编译),并且ppEnabledExtensionNames
已被初始化为 NULL。根据以下文档vkEnumerateInstanceExtensionProperties()
:
如果
pProperties
为 NULL,则返回可用扩展属性的数量pPropertyCount
。否则,pPropertyCount
必须指向用户设置的变量,该变量指向pProperties
数组中的元素数量,并在返回时用实际写入的结构数覆盖该变量pProperties
。
由于pPropertCount
是NULL,vkEnumerateInstanceExtensionProperties()
所以无处写入属性计数!这肯定会导致访问冲突试图写入地址 0x00000000000000000。
文档清除状态:
pPropertyCount
必须uint32_t
是指向值的有效指针
最重要的是,无论如何,您的调用在vkEnumerateInstanceExtensionProperties()
逻辑上都是错误的,因为第三个参数需要一个指向VkExtensionProperties
结构数组的指针,而是VulkanCreateInfo.ppEnabledExtensionNames
指向const char*
UTF-8 字符串数组的指针。
换句话说,您不应该使用vkEnumerateInstanceExtensionProperties()
来初始化调用的标准vkCreateInstance()
。你完全在滥用vkEnumerateInstanceExtensionProperties()
. 您可能打算SDL_Vulkan_GetInstanceExtensions()
改用,例如:
uint32_t ExtensionCount = 0;
if (!SDL_Vulkan_GetInstanceExtensions(NULL, &ExtensionCount, NULL))
{
...
}
const char **ExtensionNames = (const char **) SDL_malloc(sizeof(const char *) * ExtensionCount);
if (!ExtensionNames)
{
...
}
if (!SDL_Vulkan_GetInstanceExtensions(NULL, &ExtensionCount, ExtensionNames))
{
SDL_free(ExtensionNames);
...
}
VulkanCreateInfo.enabledExtensionCount = ExtensionCount;
VulkanCreateInfo.ppEnabledExtensionNames = ExtensionNames;
if (vkCreateInstance(&VulkanCreateInfo, 0, &VulkanInstance) != VK_SUCCESS)
{
...
}
SDL_free(ExtensionNames);
...
推荐阅读
- reactjs - React 按钮 onClick 事件调用其他组件
- cmd - findstr 按空格分割并显示第三个单词
- python - 根据熊猫中的前一行创建新的平均列
- python - Zip_Longest 返回一个结果
- python - 迭代 .csv 文件并分别命名数据框
- go - 如何在 go-lang 中导入包或如何正确构建包结构?
- c# - 使用 Postgres 和 EF 核心解决“列为空”问题
- javascript - 尽管 'enabled' 设置为 false,React Query 仍会继续重试
- oracle - 从全局临时表中选择数据
- javascript - 我们如何在基于类的组件中调用 react js 的递归函数