Memory leaks in vulkan

Hey guys, I’m just getting into Vulkan and decided to write a 2D game in C so I can learn.

Because this is C, I’m using memory debugging tools to help detect memory leaks in my application. Since Vulkan allows you to provide your own allocators I thought it would be a cool idea to pass in my debug allocators.

Long story short, the only thing I’m doing is calling vkCreateInstance() followed by vkDestroyInstance() and it produces 45 memory leaks.
pastebin com/td5iX7Z0 (I can’t post URLs because I’m new, sorry)

I do this by keeping track of each call to malloc() and then matching the memory address to each call to free(). Any remaining items in the list of allocations after the program has terminated is printed to stderr along with backtraces.

Here’s the thing though: If I create and destroy an instance two times, the memory leak count remains at 45. I would have expected it to go up to 90, but it doesn’t, so this indicates to me that there is some global state not being cleaned up by Vulkan.

What’s also interesting is that vkDestroyInstance() throws a “WARNING: free(NULL)” with this backtrace:

WARNING: FREE(NULL)
  backtrace to where free() was called:
      /home/thecomet/documents/programming/cpp/clither/build/lib/libutil.so(get_backtrace+0x35) [0x7f655b965593]
      /home/thecomet/documents/programming/cpp/clither/build/lib/libutil.so(free_wrapper_debug+0x125) [0x7f655b9601d6]
      /home/thecomet/documents/programming/cpp/clither/build/lib/libgame.so(+0x1e1b) [0x7f655bb8be1b]
      /usr/lib64/libnvidia-glcore.so.375.20(+0x13aa5ce) [0x7f6559afc5ce]
      ./libvulkan.so.1(+0x88d2) [0x7f655aa6d8d2]
      ./libvulkan.so.1(vkDestroyInstance+0x98) [0x7f655aa761e8]
      /home/thecomet/documents/programming/cpp/clither/build/lib/libgame.so(renderer_destroy+0x51) [0x7f655bb8c073]
      /home/thecomet/documents/programming/cpp/clither/build/lib/libgame.so(game_destroy+0x42) [0x7f655bb8c320]
      /home/thecomet/documents/programming/cpp/clither/build/bin/clither(main+0x4a) [0x400bf0]
      /lib64/libc.so.6(__libc_start_main+0xf0) [0x7f655aec7620]
      /home/thecomet/documents/programming/cpp/clither/build/bin/clither(_start+0x29) [0x400ad9]

Is there some cleanup function I’m supposed to be calling, other than vkDestroyInstance()?

What could be causing this?

I’m using VulkanSDK 1.0.33.0 and I’m using the latest nvidia drivers (375.20-r1) for my GTM 520 card. This is on 64-bit linux.

I am not sure what you mean by “throws”. But in Vulkan it is allowed to request free of NULL and your allocator must handle it correctly.

Maybe there are leaks. Why not… Maybe someone used wrong allocator…

  • try running with and without layers
  • make sure you provide the exact same allocator to vkCreate as to vkDestroy
  • make sure you are counting reallocs correctly
  • there can be NULLs and possibly zero sizes, make sure you count that correctly
  • theoretically you should check alignment
  • if sure about this, post it to the developers, so they can fix their crap

Hey, thanks for the list of things to check.

[ul][li]I’m running without layers, just the core.
[/li][li]There are no calls being made to realloc() (see code below)
[/li][li]I’m handling NULL and zero-sizes correctly
[/li][li]I’m not checking alignment, but I don’t think it matters in this case[/ul]
[/li]
Here is a nearly complete example reproducing the issue:

static int g_counter = 0;
static void* alloc_fun(void* pUserData, size_t  size,  size_t  alignment, VkSystemAllocationScope allocationScope)
{
    g_counter++;
    return malloc(size);
}

static void* realloc_fun(void* pUserData, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
{
    assert(0);
    return NULL;
}

static void free_fun(void* pUserData, void* pMemory)
{
    g_counter--;
    free(pMemory);
}

VkAllocationCallbacks g_allocators = {
    NULL,                 /* pUserData;             */
    alloc_fun,            /* pfnAllocation;         */
    realloc_fun,          /* pfnReallocation;       */
    free_fun,             /* pfnFree;               */
    NULL,                 /* pfnInternalAllocation; */
    NULL                  /* pfnInternalFree;       */
};

void init_renderer()
{
    VkInstance instance;
    VkInstanceCreateInfo instance_info = {0};
    VkApplicationInfo application_info = {0};

    load_vulkan_library();

    application_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; /* sType is a member of all structs  */
    application_info.pNext = NULL;                               /* as is pNext and flag              */
    application_info.pApplicationName = "Test";               /* The name of our application       */
    application_info.pEngineName = NULL;                         /* The name of the engine            */
    application_info.engineVersion = 1;                          /* The version of the engine         */
    application_info.apiVersion = VK_MAKE_VERSION(1, 0, 0);      /* The version of Vulkan we're using */

    instance_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instance_info.pApplicationInfo = &application_info;
    instance_info.enabledLayerCount = 0;
    instance_info.ppEnabledLayerNames = NULL;
    instance_info.enabledExtensionCount = 0;
    instance_info.ppEnabledExtensionNames = NULL;

    vkCreateInstance(
            &instance_info,
            &g_allocators,
            &instance);

    vkDestroyInstance(instance, &g_allocators);
}

int main()
{
    init_renderer();
    printf("counter: %d
", g_counter);
}

I’ve omitted load_vulkan_library() and any error checking for clarity.

Upon running this code, the output is:

counter: 44

150 allocations and 106 deallocations. One of the deallocations passes NULL which I find interesting.

Tried to reproduce this on my platform (W10 x64, R9 280X 16.11.5, LnG SDK 1.0.33):

19728 allocs, and 19728 frees (kinda excessive eh?).
0 reallocs
4 frees of nullptr (not counted above).

0 internal allocs and 0 internal frees.

So everything valid for me.
Your code gives me -4 (consistent with the free( nullptr ) count). So probably no error on your end.
Do not see any support of the behavior you reported in the spec.
-> Gonna label it “driver bug”.

Cool, thanks for testing.

What would you recommend I do to help fix this? Who can I report this to?

[QUOTE=TheComet;41549]Cool, thanks for testing.

What would you recommend I do to help fix this? Who can I report this to?[/QUOTE]

the people who wrote the buggy driver