c++ - VkSurfaceKHR 指针的值在函数调用后发生变化,无需任何显式赋值

标签 c++ c vulkan

这是来自 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;

并将每个表面(数字)传递给不同的函数。

最佳答案

天哪,这是一次有趣的旅程,最终让我完全被震撼了;简单地说 - 缺乏天才。

经过一段时间的寻找,尝试调试一些东西,我最终发现了一个非常非常的愚蠢错误,它导致了各种各样的问题。

我通过使用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);

我在想,“是的,我需要大小来存储这个 lQueueFamilies 数组中的信息”,并且我分配了内存来存储 *lQueueFamilies 中的信息乘以计数。

但是这是错误的!

我需要的是

(*gQueueFamilyIndicesList) = malloc(sizeof(QueueFamilyIndices) * lQueueFamilyCount);

因为我需要 gQueueFamilyIndi​​cesList 来存储来自 VkQueueFamilyProperties 的特定信息,而不是结构本身。

我不知道我是怎么错过的。感谢 @krOoze 建议使用 const 和 @solidpixel 来建议这可能是内存损坏,事实确实如此。

关于c++ - VkSurfaceKHR 指针的值在函数调用后发生变化,无需任何显式赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59917462/

相关文章:

c++ - 访问特定地址时是否可以强制访问冲突?

c - 发送原始 eth 数据包。我什么时候应该关闭套接字?

c - 段错误 : arr[(i * 16) % arrLen] vs arr[i % arrLen]

vulkan 扩展 : which are supported by whom?

c++ - 如何在 Google Test 中为一个夹具运行多个测试用例?

c++ - 英特尔c/c++编译器: "could not locate executable icc" (and ecc)

c++ - 使用非类型模板参数重复调用函数

C 指向函数的指针

c++ - 如何在 Vulkan 中子分配缓冲区

vulkan - 带有屏障或渲染 channel 的移动图像布局