VkSurfaceKHR 指针的值在没有任何显式赋值的函数调用后发生变化
VkSurfaceKHR pointer's value changes after a function call without any explicit assignments
这是来自 Vulkan 验证层的删节错误消息
Invalid VkSurfaceKHR Object 0x1000000002.
Objects: 1
[0] 0x1000000002, type: 1000000000, name: NULL
由此函数抛出
populateQueueFamilies(&physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, &surface);
现在这不应该发生,因为
populatePhysicalDevice(&instance, &physicalDevice, &surface);
populateQueueFamilies(&physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, &surface);
它之前的函数也使用了 surface
变量并且没有抛出任何错误!
我很生气一些打印函数,看看变量是否有问题,瞧
printf("%p\n", surface); // prints - 0x10000000001
populatePhysicalDevice(&instance, &physicalDevice, &surface);
printf("%p\n", surface); // prints - 0x10000000002
populateQueueFamilies(&physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, &surface);
我知道当您将局部变量的地址分配给指针时会发生此类问题。
但我认为这不是这里发生的事情,因为 populateQueueFamilies
中唯一触及 surface
var 的函数是这个函数:
void populateSwapchainSupportDetails(SwapchainSupportDetails* gSwapchainSupportDetails,
VkPhysicalDevice* gPhysicalDevice,
VkSurfaceKHR* gSurface)
{
VkSurfaceCapabilitiesKHR lCapabilities;
uint32_t formatCount;
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(*gPhysicalDevice, *gSurface, &lCapabilities);
uint32_t gFormatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(*gPhysicalDevice, *gSurface, &gFormatCount, VK_NULL_HANDLE);
VkSurfaceFormatKHR lFormats[gFormatCount];
if (gFormatCount != 0)
{
vkGetPhysicalDeviceSurfaceFormatsKHR(*gPhysicalDevice, *gSurface, &gFormatCount, lFormats);
}
uint32_t gPresentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(*gPhysicalDevice, *gSurface, &gPresentModeCount, VK_NULL_HANDLE);
VkPresentModeKHR lPresentModes[gPresentModeCount];
if (gPresentModeCount != 0)
{
vkGetPhysicalDeviceSurfacePresentModesKHR(
*gPhysicalDevice, *gSurface, &gPresentModeCount, lPresentModes);
}
gSwapchainSupportDetails->capabilities = lCapabilities;
gSwapchainSupportDetails->formatCount = gFormatCount;
gSwapchainSupportDetails->presentModeCount = gPresentModeCount;
gSwapchainSupportDetails->formats = malloc(sizeof(lFormats));
memcpy(gSwapchainSupportDetails->formats, lFormats, sizeof(lFormats));
gSwapchainSupportDetails->formats = malloc(sizeof(lPresentModes));
memcpy(gSwapchainSupportDetails->formats, lPresentModes, sizeof(lPresentModes));
有一个有效的临时修复:
VkSurfaceKHR surface1 = surface;
VkSurfaceKHR surface2 = surface;
并将每个 surface(number)
传递给不同的函数。
哦,天哪,这是一次有趣的旅程,最终让我完全被震撼了;轻松地说 - 缺乏 天才。
找了一段时间后,尝试调试东西,我最终发现了一个真正 真正 导致各种问题的愚蠢错误。
我是通过 valgrind
得到的。
我运行它使用这个命令
valgrind\
--leak-check=full\
--leak-resolution=high\
--show-leak-kinds=all\
--xtree-leak=yes\
--track-origins=yes\
--show-mismatched-frees=yes\
它给了我很多信息,这里是它们的删节版
Invalid write of size 8
at <someaddress>: populateQueueFamilies ()
...
...
Invalid write of size 8
at <someaddress>: populateQueueFamilies ()
...
...
Invalid write of size 8
at <someaddress>: populateQueueFamilies ()
...
...
无效写入意味着我正在写入无效的内存位置。
一些谷歌搜索告诉我错误消息几乎总是由于 malloc
.
的错误使用而发生
这是我的 populateQueueFamilies
函数
void populateQueueFamilies(const VkPhysicalDevice* gPhysicalDevice,
const VkSurfaceKHR* surface,
uint32_t* gQueueFamilyCount,
QueueFamilyIndices** gQueueFamilyIndicesList)
{
uint32_t lQueueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(*gPhysicalDevice, &lQueueFamilyCount, VK_NULL_HANDLE);
VkQueueFamilyProperties lQueueFamilies[lQueueFamilyCount];
vkGetPhysicalDeviceQueueFamilyProperties(*gPhysicalDevice, &lQueueFamilyCount, lQueueFamilies);
VkBool32 presentFamilySupported;
(*gQueueFamilyIndicesList) = malloc(sizeof(*lQueueFamilies) * lQueueFamilyCount);
for (int i = 0; i < lQueueFamilyCount; ++i)
{
QueueFamilyIndices gQueueFamilyIndices;
populateQueueFamilyQueueIndices(lQueueFamilies[i], i, &gQueueFamilyIndices);
presentFamilySupported = false;
vkGetPhysicalDeviceSurfaceSupportKHR(*gPhysicalDevice, i, *surface, &presentFamilySupported);
gQueueFamilyIndices.presentFamilySupportQueueIndex = presentFamilySupported ? i : -1;
(*gQueueFamilyIndicesList)[i] = gQueueFamilyIndices;
}
*gQueueFamilyCount = lQueueFamilyCount;
}
那一行
(*gQueueFamilyIndicesList) = malloc(sizeof(*lQueueFamilies) * lQueueFamilyCount);
在我的脑海里我在想,"yes, I need size to store information from this lQueueFamilies
array" 并且我分配了内存来存储来自 *lQueueFamilies
次计数的信息。
但这是错误的!
我需要的是
(*gQueueFamilyIndicesList) = malloc(sizeof(QueueFamilyIndices) * lQueueFamilyCount);
因为我需要 gQueueFamilyIndicesList
来存储来自 VkQueueFamilyProperties
的特定信息,而不是结构本身。
我不知道我是怎么错过的。感谢@krOoze 建议使用 const
和 @solidpixel 建议这可能是内存损坏,确实如此。
这是来自 Vulkan 验证层的删节错误消息
Invalid VkSurfaceKHR Object 0x1000000002.
Objects: 1
[0] 0x1000000002, type: 1000000000, name: NULL
由此函数抛出
populateQueueFamilies(&physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, &surface);
现在这不应该发生,因为
populatePhysicalDevice(&instance, &physicalDevice, &surface);
populateQueueFamilies(&physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, &surface);
它之前的函数也使用了 surface
变量并且没有抛出任何错误!
我很生气一些打印函数,看看变量是否有问题,瞧
printf("%p\n", surface); // prints - 0x10000000001
populatePhysicalDevice(&instance, &physicalDevice, &surface);
printf("%p\n", surface); // prints - 0x10000000002
populateQueueFamilies(&physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, &surface);
我知道当您将局部变量的地址分配给指针时会发生此类问题。
但我认为这不是这里发生的事情,因为 populateQueueFamilies
中唯一触及 surface
var 的函数是这个函数:
void populateSwapchainSupportDetails(SwapchainSupportDetails* gSwapchainSupportDetails,
VkPhysicalDevice* gPhysicalDevice,
VkSurfaceKHR* gSurface)
{
VkSurfaceCapabilitiesKHR lCapabilities;
uint32_t formatCount;
uint32_t presentModeCount;
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(*gPhysicalDevice, *gSurface, &lCapabilities);
uint32_t gFormatCount;
vkGetPhysicalDeviceSurfaceFormatsKHR(*gPhysicalDevice, *gSurface, &gFormatCount, VK_NULL_HANDLE);
VkSurfaceFormatKHR lFormats[gFormatCount];
if (gFormatCount != 0)
{
vkGetPhysicalDeviceSurfaceFormatsKHR(*gPhysicalDevice, *gSurface, &gFormatCount, lFormats);
}
uint32_t gPresentModeCount;
vkGetPhysicalDeviceSurfacePresentModesKHR(*gPhysicalDevice, *gSurface, &gPresentModeCount, VK_NULL_HANDLE);
VkPresentModeKHR lPresentModes[gPresentModeCount];
if (gPresentModeCount != 0)
{
vkGetPhysicalDeviceSurfacePresentModesKHR(
*gPhysicalDevice, *gSurface, &gPresentModeCount, lPresentModes);
}
gSwapchainSupportDetails->capabilities = lCapabilities;
gSwapchainSupportDetails->formatCount = gFormatCount;
gSwapchainSupportDetails->presentModeCount = gPresentModeCount;
gSwapchainSupportDetails->formats = malloc(sizeof(lFormats));
memcpy(gSwapchainSupportDetails->formats, lFormats, sizeof(lFormats));
gSwapchainSupportDetails->formats = malloc(sizeof(lPresentModes));
memcpy(gSwapchainSupportDetails->formats, lPresentModes, sizeof(lPresentModes));
有一个有效的临时修复:
VkSurfaceKHR surface1 = surface;
VkSurfaceKHR surface2 = surface;
并将每个 surface(number)
传递给不同的函数。
哦,天哪,这是一次有趣的旅程,最终让我完全被震撼了;轻松地说 - 缺乏 天才。
找了一段时间后,尝试调试东西,我最终发现了一个真正 真正 导致各种问题的愚蠢错误。
我是通过 valgrind
得到的。
我运行它使用这个命令
valgrind\
--leak-check=full\
--leak-resolution=high\
--show-leak-kinds=all\
--xtree-leak=yes\
--track-origins=yes\
--show-mismatched-frees=yes\
它给了我很多信息,这里是它们的删节版
Invalid write of size 8
at <someaddress>: populateQueueFamilies ()
...
...
Invalid write of size 8
at <someaddress>: populateQueueFamilies ()
...
...
Invalid write of size 8
at <someaddress>: populateQueueFamilies ()
...
...
无效写入意味着我正在写入无效的内存位置。
一些谷歌搜索告诉我错误消息几乎总是由于 malloc
.
这是我的 populateQueueFamilies
函数
void populateQueueFamilies(const VkPhysicalDevice* gPhysicalDevice,
const VkSurfaceKHR* surface,
uint32_t* gQueueFamilyCount,
QueueFamilyIndices** gQueueFamilyIndicesList)
{
uint32_t lQueueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(*gPhysicalDevice, &lQueueFamilyCount, VK_NULL_HANDLE);
VkQueueFamilyProperties lQueueFamilies[lQueueFamilyCount];
vkGetPhysicalDeviceQueueFamilyProperties(*gPhysicalDevice, &lQueueFamilyCount, lQueueFamilies);
VkBool32 presentFamilySupported;
(*gQueueFamilyIndicesList) = malloc(sizeof(*lQueueFamilies) * lQueueFamilyCount);
for (int i = 0; i < lQueueFamilyCount; ++i)
{
QueueFamilyIndices gQueueFamilyIndices;
populateQueueFamilyQueueIndices(lQueueFamilies[i], i, &gQueueFamilyIndices);
presentFamilySupported = false;
vkGetPhysicalDeviceSurfaceSupportKHR(*gPhysicalDevice, i, *surface, &presentFamilySupported);
gQueueFamilyIndices.presentFamilySupportQueueIndex = presentFamilySupported ? i : -1;
(*gQueueFamilyIndicesList)[i] = gQueueFamilyIndices;
}
*gQueueFamilyCount = lQueueFamilyCount;
}
那一行
(*gQueueFamilyIndicesList) = malloc(sizeof(*lQueueFamilies) * lQueueFamilyCount);
在我的脑海里我在想,"yes, I need size to store information from this lQueueFamilies
array" 并且我分配了内存来存储来自 *lQueueFamilies
次计数的信息。
但这是错误的!
我需要的是
(*gQueueFamilyIndicesList) = malloc(sizeof(QueueFamilyIndices) * lQueueFamilyCount);
因为我需要 gQueueFamilyIndicesList
来存储来自 VkQueueFamilyProperties
的特定信息,而不是结构本身。
我不知道我是怎么错过的。感谢@krOoze 建议使用 const
和 @solidpixel 建议这可能是内存损坏,确实如此。