Search code examples
csdlvulkan

After assignment const char* to const char** I have an error


Here my code:

const char* sdl_extensions;
const char** sdl_extensions_list;
if (!SDL_Vulkan_GetInstanceExtensions(p_window, &sdl_extension_count, &sdl_extensions)) 
{   
    printf("sdl_extension_count = %i\n", sdl_extension_count);
    printf("[ERROR]: SDL_Vulkan_GetInstanceExtensions _2\n");
    exit(0);
}
else
{
    for(int i = 0; i < sdl_extension_count; i++)
    {
        printf("sdl_extension_%i = %s\n", i, *(&sdl_extensions + i));
    }

    sdl_extensions_list = &sdl_extensions;
    
    for(int i = 0; i < sdl_extension_count; i++)
    {
        printf("sdl_extension_%i = %s\n", i, *(&sdl_extensions + i));
    }
}

and here the output:

sdl_extension_count = 2
sdl_extension_0 = VK_KHR_surface
sdl_extension_1 = VK_KHR_xlib_surface
sdl_extension_0 = VK_KHR_surface
sdl_extension_1 = diz?�

Why after line "sdl_extensions_list = &sdl_extensions;" do I have wrong output (sdl_extension_1 = diz?�)?

Thanks!


Solution

  • From reading the SDL_Vulkan_GetInstanceExtensions documentation what you need to pass is an array of pointers to SDL_Vulkan_GetInstanceExtensions, and then the function initializes those pointers.

    The example in the above documentation also shows that you need to call SDL_Vulkan_GetInstanceExtensions twice: First to get the element count; Then again after you created your array to get the actual list.

    In C the code to do it would be something like this:

    unsigned int count;
    SDL_Vulkan_GetInstanceExtensions(window, &count, NULL);
    
    const char **extensions = malloc(sizeof(const char *) * count);
    
    SDL_Vulkan_GetInstanceExtensions(window, &count, extensions);
    
    for (size_t i = 0; i < count; ++i)
    {
        printf("Extension %zu: %s\n", i, extensions[i]);
    }
    

    [Important note: Error handling is left as an exercise to the reader]

    Remember to free the memory you malloc after you're done with it.


    To explain the difference between &sdl_extensions in your code and extensions in my example, lets draw them and see their difference.

    First sdl_extensions and the pointer &sdl_extensions:

    +-----------------+      +----------------+
    | &sdl_extensions | ---> | sdl_extensions |
    +-----------------+      +----------------+
    

    Then extensions from my example (assuming a count of 2):

    +------------+      +---------------+---------------+
    | extensions | ---> | extensions[0] | extensions[1] |
    +------------+      +---------------+---------------+
    

    From these two images it's easy to see a major problem here: &sdl_extensions points to a single const char * "element", while extensions point to an array of two elements.

    Because SDL_Vulkan_GetInstanceExtensions treats the argument as a pointer to the first element of an array containing count pointers, your code will cause SDL_Vulkan_GetInstanceExtensions to write out of bounds of your single-element "array", which leads to undefined behavior.