英文:
What is the cause of the segmentation fault during the vulkan instance creation?
问题
我正在编写一个使用Vulkan的应用程序,但我注意到它不起作用。我一直在删除代码,直到我达到了这个点:
#include <vulkan/vulkan.h>
#include <iostream>
int main()
{
VkApplicationInfo info{};
info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
info.pNext = nullptr;
info.apiVersion = VK_VERSION_1_3;
info.applicationVersion = 1;
info.engineVersion = 0;
info.pApplicationName = "App";
info.pEngineName = nullptr;
VkInstanceCreateInfo instanceInfo{};
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pNext = nullptr;
instanceInfo.flags = 0;
instanceInfo.enabledExtensionCount = 0;
instanceInfo.enabledLayerCount = 0;
instanceInfo.ppEnabledExtensionNames = nullptr;
instanceInfo.ppEnabledLayerNames = nullptr;
instanceInfo.pApplicationInfo = &info;
VkInstance instance;
auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);
if (code != VK_SUCCESS)
{
std::cout << "failed to create instance" << std::endl;
return -1;
}
else vkDestroyInstance(instance, nullptr);
return 0;
}
我正在使用FreeBSD 13.2和Clang 16.0.6进行编译。我已经安装了Vulkan软件包:
$ pkg info vulkan*
vulkan-caps-viewer-3.31
vulkan-extension-layer-1.3.254
vulkan-headers-1.3.254
vulkan-loader-1.3.254
vulkan-tools-1.3.254
vulkan-validation-layers-1.3.254
使用带有调试符号的可执行文件运行GDB时,出现以下错误:
程序收到信号SIGSEGV,分段错误。
地址未映射到对象。
0x0000000800595300 in ?? () from /lib/libc.so.7
(gdb) backtrace
#0 0x0000000800595300 in ?? () from /lib/libc.so.7
#1 0x00000008005a04b6 in vsnprintf () from /lib/libc.so.7
#2 0x00000008002e3dec in ?? () from /usr/local/lib/libvulkan.so.1
#3 0x00000008002c1278 in ?? () from /usr/local/lib/libvulkan.so.1
#4 0x00000008002ded9f in ?? () from /usr/local/lib/libvulkan.so.1
#5 0x00000008002e1579 in ?? () from /usr/local/lib/libvulkan.so.1
#6 0x00000008002e7ca6 in vkCreateInstance () from /usr/local/lib/libvulkan.so.1
#7 0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
(gdb) frame 7
#7 0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
26 auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);
(gdb) p instanceInfo
$1 = {sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, pNext = 0x0, flags = 0, pApplicationInfo = 0x7fffffffe6f8, enabledLayerCount = 0,
ppEnabledLayerNames = 0x0, enabledExtensionCount = 0, ppEnabledExtensionNames = 0x0}
我预期实例应该成功创建。
英文:
I am writing a vulkan powered app, and I noticed it wasn't working. I kept on removing code until i reached this:
#include <vulkan/vulkan.h>
#include <iostream>
int main()
{
VkApplicationInfo info{};
info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
info.pNext = nullptr;
info.apiVersion = VK_VERSION_1_3;
info.applicationVersion = 1;
info.engineVersion = 0;
info.pApplicationName = "App";
info.pEngineName = nullptr;
VkInstanceCreateInfo instanceInfo{};
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pNext = nullptr;
instanceInfo.flags = 0;
instanceInfo.enabledExtensionCount = 0;
instanceInfo.enabledLayerCount = 0;
instanceInfo.ppEnabledExtensionNames = nullptr;
instanceInfo.ppEnabledLayerNames = nullptr;
instanceInfo.pApplicationInfo = &info;
VkInstance instance;
auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);
if (code != VK_SUCCESS)
{
std::cout << "failed to create instance" << std::endl;
return -1;
}
else vkDestroyInstance(instance, nullptr);
return 0;
}
I am using freebsd 13.2 with clang 16.0.6 to compile this.
I have installed the vulkan packages:
$ pkg info vulkan*<br>
vulkan-caps-viewer-3.31
vulkan-extension-layer-1.3.254
vulkan-headers-1.3.254
vulkan-loader-1.3.254
vulkan-tools-1.3.254
vulkan-validation-layers-1.3.254<br>
Running gdb on the executable with debugging symbols gives:
Program received signal SIGSEGV, Segmentation fault.
Address not mapped to object.
0x0000000800595300 in ?? () from /lib/libc.so.7
(gdb) backtrace
#0 0x0000000800595300 in ?? () from /lib/libc.so.7
#1 0x00000008005a04b6 in vsnprintf () from /lib/libc.so.7
#2 0x00000008002e3dec in ?? () from /usr/local/lib/libvulkan.so.1
#3 0x00000008002c1278 in ?? () from /usr/local/lib/libvulkan.so.1
#4 0x00000008002ded9f in ?? () from /usr/local/lib/libvulkan.so.1
#5 0x00000008002e1579 in ?? () from /usr/local/lib/libvulkan.so.1
#6 0x00000008002e7ca6 in vkCreateInstance () from /usr/local/lib/libvulkan.so.1
#7 0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
(gdb) frame 7
#7 0x000000000020b569 in main () at /home/chris/projects/freestick/src/main.cpp:26
26 auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);
(gdb) p instanceInfo
$1 = {sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, pNext = 0x0, flags = 0, pApplicationInfo = 0x7fffffffe6f8, enabledLayerCount = 0,
ppEnabledLayerNames = 0x0, enabledExtensionCount = 0, ppEnabledExtensionNames = 0x0}
I expected the instance to get created successfully.
答案1
得分: 0
我认为这只是在您的 VkApplicationInfo
结构中使用了错误的宏的简单情况。我不确定在您的系统上 VK_VERSION_1_3
展开为什么,因为我只有 VK_VERSION_1_2
,但它只展开为 1
。
在我的代码中,我仅仅是将那个宏替换为看似正确的宏。请注意,我通过运行 /usr/bin/vulkaninfo | head
并注意输出来获取正确的版本号来填充该宏。例如:
Vulkan Instance Version: 1.2.131
你的版本可能会不同。为了完整起见,这是我没有再发生段错误的代码(我在ubuntu上使用了稍微不同版本的vulkan,因此有额外的头文件):
#include <iostream>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan.hpp>
int main(){
VkApplicationInfo info{};
info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
info.pNext = nullptr;
info.apiVersion = VK_MAKE_VERSION(1, 2, 131);
info.applicationVersion = 1;
info.engineVersion = 0;
info.pApplicationName = "App";
info.pEngineName = nullptr;
VkInstanceCreateInfo instanceInfo{};
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pNext = nullptr;
instanceInfo.flags = 0;
instanceInfo.enabledExtensionCount = 0;
instanceInfo.enabledLayerCount = 0;
instanceInfo.ppEnabledExtensionNames = nullptr;
instanceInfo.ppEnabledLayerNames = nullptr;
instanceInfo.pApplicationInfo = &info;
VkInstance instance;
auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);
if (code != VK_SUCCESS){
std::cout << "failed to create instance" << std::endl;
return -1;
} else vkDestroyInstance(instance, nullptr);
return 0;
}
补充说明,看起来您也可以通过以下方式轻松地以编程方式获取此信息,从这个答案中偷来:
通过代码检查(无论使用哪种语言,只要您有头文件),可以通过使用 vkGetPhysicalDeviceProperties 查询设备属性来完成。VkPhysicalDeviceProperties 结构的 apiVersion 成员包含该设备的最大支持版本。只需移位位或使用头文件中的版本宏即可获得可读的版本号(主要版本.次要版本.修订版本)。
英文:
I think its a simple case of using the wrong macro in your VkApplicationInfo
struct. I am not sure what VK_VERSION_1_3
expands to on your system as I only have VK_VERSION_1_2
, but that only expands to 1
.
In my code here, I have done nothing but replace that macro with the seemingly correct macro. Note that I obtained the correct version numbers to fill the macro with by running /usr/bin/vulkaninfo | head
and noting the output
Vulkan Instance Version: 1.2.131
And yours will likely be different. For completeness, this is the code I have which no longer segfaults (I am on ubuntu with a slightly different version of vulkan, hence the extra headers):
#include <iostream>
#include <vulkan/vulkan.h>
#include <vulkan/vulkan_core.h>
#include <vulkan/vulkan.hpp>
int main(){
VkApplicationInfo info{};
info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
info.pNext = nullptr;
info.apiVersion = VK_MAKE_VERSION(1, 2, 131);
info.applicationVersion = 1;
info.engineVersion = 0;
info.pApplicationName = "App";
info.pEngineName = nullptr;
VkInstanceCreateInfo instanceInfo{};
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pNext = nullptr;
instanceInfo.flags = 0;
instanceInfo.enabledExtensionCount = 0;
instanceInfo.enabledLayerCount = 0;
instanceInfo.ppEnabledExtensionNames = nullptr;
instanceInfo.ppEnabledLayerNames = nullptr;
instanceInfo.pApplicationInfo = &info;
VkInstance instance;
auto code = vkCreateInstance(&instanceInfo, nullptr, &instance);
if (code != VK_SUCCESS){
std::cout << "failed to create instance" << std::endl;
return -1;
} else vkDestroyInstance(instance, nullptr);
return 0;
}
Editing to note that it seems like you could also easily get this information programatically by doing the following, stolen from this answer:
> Checking via code (no matter what language, as long as you got headers) can be done by querying device properties via vkGetPhysicalDeviceProperties. The apiVersion member of the VkPhysicalDeviceProperties struct contains the maximum supported version for that device. Just shift the bits or use the version macros from the headers to get a humnan readable version (major.minor.patch).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论