You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

g_array_append_vals断言失败及g_ptr_array_extend_and_steal崩溃问题排查

Vulkan扩展检查CMake项目崩溃问题解决

问题背景

开发Vulkan扩展检查的CMake项目时,程序运行后瞬间退出,终端输出断言失败错误。先后尝试GArray和GPtrArray两种容器,均遇到问题:

初始GArray实现的问题

使用GArray编写的函数触发g_array_append_vals的'array'断言失败,核心原因是未初始化requiredExtensions数组,指针类型转换尝试无效。

初始代码:

GArray* glfwExtensions, *requiredExtensions;
uint_fast32_t 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;
}

终端错误输出:

(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

改用GPtrArray后的问题

切换到GPtrArray后,调用g_ptr_array_extend_and_steal时程序崩溃,但单独用g_ptr_array_add添加元素可以正常运行,导致无法批量启用验证层和其他扩展。

修改后代码:

GPtrArray *glfwExtensions, *requiredExtensions;
uint_fast32_t 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); <-- 此代码正常运行,原因何在?

    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;
}

问题原因分析

g_ptr_array_extend_and_steal崩溃的核心原因是临时栈数组的生命周期问题:

  • 代码中(char*[]){VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME}是栈上的临时数组,语句执行结束后会被销毁。
  • g_ptr_array_new_take会接管传入的指针数组所有权,但临时数组销毁后,GPtrArray内部持有了野指针。
  • 调用g_ptr_array_extend_and_steal时访问这些野指针,触发程序崩溃。
  • 而g_ptr_array_add只是添加字符串字面量的指针,字符串字面量存储在程序全局只读数据区,生命周期贯穿整个程序,因此不会出现野指针问题。

解决方案

方案1:逐个调用g_ptr_array_add添加扩展

直接逐个添加扩展名称,避免临时数组的生命周期问题:

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);
    
    if (enableValidationLayers) {
        g_ptr_array_add(requiredExtensions, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
    }

    return EXIT_SUCCESS;
}

方案2:动态分配数组后使用g_ptr_array_new_take

若需批量添加,可动态分配数组存储扩展名称,确保生命周期足够:

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);

    // 动态分配数组存储扩展
    gpointer* portabilityExt = g_new(gpointer, 1);
    portabilityExt[0] = (gpointer)VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME;
    g_ptr_array_extend_and_steal(requiredExtensions, g_ptr_array_new_take(portabilityExt, 1, NULL));

    if (enableValidationLayers) {
        gpointer* debugExt = g_new(gpointer, 1);
        debugExt[0] = (gpointer)VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
        g_ptr_array_extend_and_steal(requiredExtensions, g_ptr_array_new_take(debugExt, 1, NULL));
    }

    return EXIT_SUCCESS;
}

方案3:使用g_ptr_array_addv批量添加

GLib提供g_ptr_array_addv函数,可直接批量添加指针数组,无需创建临时GPtrArray:

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);

    // 批量添加扩展数组(末尾需以NULL结尾)
    const gpointer portabilityExts[] = {
        (gpointer)VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
        NULL
    };
    g_ptr_array_addv(requiredExtensions, portabilityExts);

    if (enableValidationLayers) {
        const gpointer debugExts[] = {
            (gpointer)VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
            NULL
        };
        g_ptr_array_addv(requiredExtensions, debugExts);
    }

    return EXIT_SUCCESS;
}

内容的提问来源于stack exchange,提问作者Brain_driver_not_found

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:23:11