C 语言中的 Vulkan 编程似乎不可避免地使用 malloc 或VLA,请看以下示例:
uint32_t physicalDeviceNumber = 0;
vkEnumeratePhysicalDevices(*instance, &physicalDeviceNumber, NULL);
VkPhysicalDevice physicalDevice[physicalDeviceNumber];
vkEnumeratePhysicalDevices(*instance, &physicalDeviceNumber, physicalDevice);
这段代码只是列举了物理设备,因为我不知道 GPU 的确切数量,所以我打电话vkEnumeratePhysicalDevices
来获取这个数字。然后再次调用它来实际初始化它们。在第二个函数调用中,第三个参数VkPhysicalDevice *pPhysicalDevices
必须是一个已定义的数组。它的长度必须等于 GPU 的数量,否则物理设备初始化将不完整。请参阅此处的规范。
问题来了,上面的代码使用了C 语言中的一个危险特性,称为VLA,或“可变长度数组”。此功能允许在堆栈上创建一个内存块,其大小为运行时生成的数字。他们绝对应该避免。这个博客告诉我们原因。
另一种解决方案是使用 malloc 来解决这个问题,我稍微更改了代码:
uint32_t physicalDeviceNumber = 0;
vkEnumeratePhysicalDevices(*instance, &physicalDeviceNumber, NULL);
VkPhysicalDevice *physicalDevice = (VkPhysicalDevice *)malloc(physicalDeviceNumber * sizeof(VkPhysicalDevice));
vkEnumeratePhysicalDevices(*instance, &physicalDeviceNumber, physicalDevice);
当然,这会破坏程序。TypeVkPhysicalDevice
实际上是一个指针,它的真正类型是struct VkPhysicalDevice_T *
,它指向一大块大小未知的内存。此外,在 vulkan 编程中使用 malloc 被认为是一个坏习惯。请参阅此处的讨论。
所以我很困惑。这个简单的函数不能安全地用于初始化我的 GPU,除非我知道我的电脑有多少 GPU。我不是 C 方面的专家,但我认为应该有比这些代码更安全的解决方案。如果您知道如何,请提供简单的 C 代码并解释原因。
ps:C++ 代码不是我想要的,我知道std::vector
可以解决这个问题,但我不会使用 C++。
malloc
如果你没有犯错,你可以使用。
您不是在分配 VkPhysicalDevices 数组,而是在分配指向VkPhysicalDevices的指针数组。并且您将数组的地址传递给 vkEnumeratePhysicalDevices,而不是指向数组的指针的地址(这会导致它在不适合的地方存储数组并覆盖其他随机内容)。
您也不需要强制转换 的返回值malloc
,尽管它也没有坏处。
uint32_t physicalDeviceNumber = 0;
vkEnumeratePhysicalDevices(*instance, &physicalDeviceNumber, NULL);
VkPhysicalDevice **physicalDevice = malloc(physicalDeviceNumber * sizeof(VkPhysicalDevice*));
vkEnumeratePhysicalDevices(*instance, physicalDeviceNumber, physicalDevice);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句