【问题标题】:Vulkan vkCreateInstance - Access violation writing location 0x0000000000000000Vulkan vkCreateInstance - 访问冲突写入位置 0x0000000000000000
【发布时间】:2020-07-02 02:23:52
【问题描述】:

我正在尝试使用 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;
}

【问题讨论】:

  • 表示有一个 NULL 指针。你忘了初始化一些东西吗?在调试器中单步执行以找出该指针应该表示的内容。
  • 请用您使用的语言进行标记。不要在 C 问题上抨击 C++。
  • 这是一个 c++ 库。我认为这可能是相关的。哪个空指针?我相信有几个。
  • 这是 C 代码。标记问题的可见部分。考虑一下:观看标签试图回答 C++ 问题的人会寻找 C++ 代码。
  • ppEnabledLayerNames = "VK_LAYER_KHRONOS_validation"。这是如何运作的?似乎是类型错误。一个是char*,另一个是char**

标签: c exception graphics vulkan


【解决方案1】:

您确定对vkCreateInstance() 的调用是什么导致崩溃了吗?我没有尝试调试您显示的代码(那是您的工作),但只是查看代码正在进行的调用,它应该是对 vkEnumerateInstanceExtensionProperties() 的调用崩溃(如果它甚至可以编译! )。

vkEnumerateInstanceExtensionProperties() 的第二个参数需要一个 uint32_t* 指针,但您传入的 uint32_t 值 (VulkanCreateInfo.enabledExtensionCount) 已初始化为 0。因此,这将使 pPropertyCount 参数成为一个 NULL 指针(如果它甚至可以编译)。

您在第三个参数中传递VulkanCreateInfo.ppEnabledExtensionNames(如果它甚至可以编译),并且ppEnabledExtensionNames 已被初始化为NULL。根据documentationvkEnumerateInstanceExtensionProperties()

如果pProperties 为NULL,则pPropertyCount 中返回可用扩展属性的数量。否则,pPropertyCount 必须指向一个由用户设置的变量,该变量指向 pProperties 数组中的元素数量,并且在返回时该变量被覆盖实际写入@987654337 的结构数量@。

由于pPropertCount 为NULL,vkEnumerateInstanceExtensionProperties() 无处可写属性计数!这肯定会导致访问冲突尝试写入地址 0x0000000000000000。

文档清除状态:

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);
...

【讨论】:

  • 我正在使用该教程的部分内容,但使用的是 SDL2 而不是 GLFW。事实证明,SDL2 提供了类似的功能来获取扩展。我会看看如何使用它。
猜你喜欢
  • 2018-08-06
  • 1970-01-01
  • 2015-08-15
  • 2020-09-04
  • 2012-12-05
  • 2013-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多