1

Trying to create a function to check available Vulkan extensions, however my executable runs and closes within a second with an error in terminal that I've barely managed to copy. It's a CMake project. The problem is in the function.

Function:

GArray* glfwExtensions, *requiredExtensions;
uint_fast32t glfwExtensionCount;
bool enableValidationLayers = true;

int __fastcall getRequiredExtensions() {
    glfwExtensions = g_array_new_take((char**)glfwGetRequiredInstanceExtensions(&glfwExtensionCount), glfwExtensionCount, false, __SIZEOF_POINTER__);
    g_array_append_vals(requiredExtensions, (const char**)(glfwExtensions->data), glfwExtensionCount);
    g_array_append_vals(requiredExtensions, (const char*[]){VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME}, 1);

    if (enableValidationLayers)
        g_array_append_vals(requiredExtensions, (const char*[]){VK_EXT_DEBUG_UTILS_EXTENSION_NAME}, 1);

    return EXIT_SUCCESS;
}

Output in terminal:

(proces:8144): GLib-CRITICAL **: 16:31:15.244: g_array_append_vals: assertion 'array' failed

(proces:8144): GLib-CRITICAL **: 16:31:15.260: g_array_append_vals: assertion 'array' failed

(proces:8144): GLib-CRITICAL **: 16:31:15.261: g_array_append_vals: assertion 'array' failed

CMakeLists.txt:

cmake_minimum_required (VERSION 3.31)

set (CMAKE_C_STANDARD 99)
set (CMAKE_C_STANDARD_REQUIRED on)

set (CMAKE_C_COMPILER "D:/msys2/ucrt64/bin/gcc.exe")
set (CMAKE_CXX_COMPILER "D:/msys2/ucrt64/bin/g++.exe")
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY "D:/my_proj/")
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}/debug")

find_package (PkgConfig REQUIRED)
pkg_check_modules (GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules (GLFW REQUIRED IMPORTED_TARGET glfw3)
pkg_check_modules (VULKAN REQUIRED IMPORTED_TARGET vulkan)
pkg_check_modules (CGLM REQUIRED IMPORTED_TARGET cglm)

option (CGLM_SHARED "Shared build" ON)
option (CGLM_STATIC "Static build" OFF)
option (CGLM_USE_C99 "" OFF)
option (CGLM_USE_TEST "Enable Tests" OFF)

project (render C)
add_executable (render D:/my_proj/render.c)

# render
target_link_options(render PRIVATE
    "-m64"
    # "-mwindows"
)

target_include_directories (render PRIVATE
    ${GLIB_INCLUDE_DIRS}
    ${GLFW_INCLUDE_DIRS}
    ${VULKAN_INCLUDE_DIRS}
    ${CGLM_INCLUDE_DIRS})

target_compile_definitions (render PRIVATE
    ${GLIB_CFLAGS_OTHER}
    ${GLFW_CFLAGS_OTHER}
    ${VULKAN_CFLAGS_OTHER}
    ${CGLM_CFLAGS_OTHER})

target_link_directories (render PRIVATE
    ${GLIB_LIBRARY_DIRS}
    ${GLFW_LIBRARY_DIRS}
    ${VULKAN_LIBRARY_DIRS}
    ${CGLM_LIBRARY_DIRS})

target_link_libraries (render PRIVATE
    ${GLIB_LIBRARIES}
    ${GLFW_LIBRARIES}
    ${VULKAN_LIBRARIES}
    ${CGLM_LIBRARIES})

I tried to change the pointers from (const char*[]) to (char**), but the result is the same. I've re-read the GLib API, but there's no explanation for that whatsoever. As I've seen in other similar post with g_ptr_array_add(), that shows my GArray pointer is NULL, but I have no clue what may happen during a simple allocation with g_array_new_take().

UPD: I forgot to initialize requiredExtensions array facepalm. Also I rewrited the function from GArray to GPtrArray by the advice of @TingPing. Now the function looks like this:

GPtrArray *glfwExtensions, *requiredExtensions;
uint_fast32t glfwExtensionCount;
bool enableValidationLayers = true;

int __fastcall getRequiredExtensions() {
    {
        const char** glfwExtTemp = (const char**)glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
        glfwExtensions = g_ptr_array_new_take((gpointer*)glfwExtTemp, glfwExtensionCount, NULL);
        requiredExtensions = g_ptr_array_copy(glfwExtensions, NULL, NULL);
    }
    // g_ptr_array_add(requiredExtensions, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); <-- THIS WORKS, WHY?!

    g_ptr_array_extend_and_steal(requiredExtensions, g_ptr_array_new_take((gpointer*)(char*[]){
        VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
    }, 1, NULL));

    if (enableValidationLayers)
        g_ptr_array_extend_and_steal(requiredExtensions, g_ptr_array_new_take((gpointer*)(char*[]){
            VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
        }, 1, NULL));

    return EXIT_SUCCESS;
}

But now I have problem with the g_ptr_array_extend_and_steal calls. When I eject them from code it works, otherwise the program crashes. I can't use validation layers due to that (No debug extension correspondingly). Moreover, when I append one single element with g_ptr_array_add it works! What is the problem of appending multiple pointers with g_ptr_array_extend_and_steal?

9
  • Can you update the code to your latest failing version with the requiredExtensions initialization? Commented Nov 24, 2024 at 9:14
  • Sure thing, updated the code Commented Nov 24, 2024 at 10:18
  • GPtrArray is definitely what you want. new_take on unowned memory is also strange. Commented Nov 25, 2024 at 1:30
  • Tried to re-write the function with GPtrArray. Same thing (updated again). But now for some reason when I use g_ptr_array_add it works, however using g_ptr_array_extend_and_steal causes the same problem as before Commented Nov 25, 2024 at 4:28
  • 2
    Documentation for g_ptr_array_new_take clearly tells that the first argument should be dynamically allocated, because later it will be passed to g_free. If you want to create an array from non-allocated C array, use g_ptr_array_new_from_array instead. Commented Nov 25, 2024 at 7:58

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.