您尚未登录。

#1 2020-06-02 23:11:55

beginner
会员
注册时间: 2019-10-07
帖子: 144

malloc断言失败,大概可能是哪些原因导致?

lua 版本:Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
环境:archlinux
宿主语言:c++
编译器:g++

malloc.c:3839: _int_malloc: Assertion `chunk_main_arena (bck->bk)' failed.
malloc.c:4036: _int_malloc: Assertion `(unsigned long) (size) >= (unsigned long) (nb)' failed.

以上2种断言失败有可能是什么原因导致?
越界?还是有其他可能
在我的程序中,是在调用vkCreateSwapchainKHR导致的。在重建交换链时,具体代码:

    const ImVec4 clear_color = ImVec4(0.2f , 0.2f , 0.2f , 1.0f);

    setup(window, g_PhysicalDevice, g_MainWindowData);
    // Main loop
    while (!glfwWindowShouldClose(window)){
        glfwPollEvents();

        if (g_SwapChainRebuild){
            g_SwapChainRebuild = false;
            ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
            ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, g_SwapChainResizeWidth, g_SwapChainResizeHeight, g_MinImageCount);
            g_MainWindowData.FrameIndex = 0;
        }

        // Start the Dear ImGui frame
        ImGui_ImplVulkan_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();
        drawWidget(g_MainWindowData);
        ImGui::EndFrame();

        ImGui::Render();
        memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
        FrameRender(wd);

        FramePresent(wd);

        renderFinish();
    }
    // Cleanup
    err = vkDeviceWaitIdle(g_Device);
    cleanup(window, g_Device);
    check_vk_result(err);
    ImGui_ImplVulkan_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

在while循环中的ImGui_ImplVulkanH_CreateWindow函数里面的vkCreateSwapchainKHR出错。具体代码可以看imgui的例子 vk glfw:imgui
重建之前vkCreateSwapchainKHR的参数信息

(gdb) p info
$2 = {sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, pNext = 0x0, flags = 0, surface = 0x20000000002, minImageCount = 3, imageFormat = VK_FORMAT_B8G8R8A8_UNORM, 
  imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, imageExtent = {width = 1916, height = 1023}, imageArrayLayers = 1, imageUsage = 16, imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, 
  queueFamilyIndexCount = 0, pQueueFamilyIndices = 0x0, preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR, compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, 
  presentMode = VK_PRESENT_MODE_FIFO_KHR, clipped = 1, oldSwapchain = 0x30000000003}

以下是出错时,使用bt得到的堆栈信息...特么出错的位置一直不一样,图片上是在分配命令buffer的时候出的错误。虽然出错的函数不一样,但都在malloc断言失败
出错时的部分信息
有时候出错的地方也会是下面的函数:

[Thread 0x7fffef7fe700 (LWP 13484) exited]

Thread 1 "Three_kingdoms" received signal SIGSEGV, Segmentation fault.
0x0000555555571c88 in FindHoveredWindow () at imgui.cpp:4350
4350	        if (!window->Active || window->Hidden)
(gdb) bt
#0  0x0000555555571c88 in FindHoveredWindow () at imgui.cpp:4350
#1  0x000055555556f6d0 in ImGui::UpdateHoveredWindowAndCaptureFlags () at imgui.cpp:3666
#2  0x0000555555570252 in ImGui::NewFrame () at imgui.cpp:3843
#3  0x00005555555ebe16 in main () at main.cpp:359
(gdb) p window
$3 = (ImGuiWindow *) 0x0
(gdb)

上面的出现的错误都因为在某些地方调用了get_table_val函数,该函数重载了多个不同类型的函数:

bool get_table_val(lua_State *L, const char *table_name, const char *key, std::string&val){
    if(!L || !table_name || !key){
        std::cout << "in function " << __FUNCTION__ << ":lua_State *L = nullptr || const char *table_name = nullptr || const char *key = nullptr" << std::endl;
        return false;
    }
    lua_getglobal(L, table_name);
    if(!lua_istable(L, -1)){
        fprintf(stderr, "error:%s is not a table name\n", table_name);
        return LUA_TNIL;
    }
    if(LUA_TSTRING != lua_getfield(L, -1, key)){
        fprintf(stderr, "error:%s[%s] type is not a string\n", table_name, key);
        return false;
    }
    val = lua_tostring(L, -1);
    lua_pop(L, 1);
    return true;
}
//最后,以下代码导致的以上错误的发生,如果注释掉则程序正常运行,以下代码都能正确获得脚本中的值:
//这些代码在setup创建的线程中执行。
    std::string skill_name;
    uint32_t skill_count = 0;
    knight_info.skills.clear();
    if(!get_table_val(g_LuaState, g_TableName[knightName].c_str(), "skill_count", skill_count)){
        fprintf(stderr, "请确认是否在%s文件中加入了该表名\n", (KNIGHT_RESOURCE_PATH + knightName + ".lua").c_str());
    }
    knight_info.skills.resize(skill_count);
    for (uint32_t i = 0; i < skill_count; ++i){
        char key[MAXBYTE] = { 0 };
        sprintf(key, "skill_%d", i + 1);
        if(get_table_val(g_LuaState, g_TableName[knightName].c_str(), key, skill_name)){//经测试,不是随机武将的时候越界;只要不调用下面的函数,则一切正常
            // KnightInformation info;
            // get_table_val(g_LuaState, skill_name.c_str(), "name", info.skills[i].name);
            // get_table_val(g_LuaState, skill_name.c_str(), "lock", info.skills[i].bLock);
            // get_table_val(g_LuaState, skill_name.c_str(), "initiative", info.skills[i].bInitiative);
            // get_table_val(g_LuaState, skill_name.c_str(), "description", info.skills[i].description);
            // get_table_val(g_LuaState, skill_name.c_str(), "effect", info.skills[i].effect_function);
            // get_table_val(g_LuaState, skill_name.c_str(), "trigger", info.skills[i].trigger_condition);
            // get_table_val(g_LuaState, skill_name.c_str(), "trigger_stage", (uint32_t&)info.skills[i].triggerStage);

            get_table_val(g_LuaState, skill_name.c_str(), "name", knight_info.skills[i].name);//name类型是std::string
            get_table_val(g_LuaState, skill_name.c_str(), "lock", knight_info.skills[i].bLock);//这是bool后面同理
            get_table_val(g_LuaState, skill_name.c_str(), "initiative", knight_info.skills[i].bInitiative);
            get_table_val(g_LuaState, skill_name.c_str(), "description", knight_info.skills[i].description);//std::string
            get_table_val(g_LuaState, skill_name.c_str(), "effect", knight_info.skills[i].effect_function);//std::string
            get_table_val(g_LuaState, skill_name.c_str(), "trigger", knight_info.skills[i].trigger_condition);//std::string
            get_table_val(g_LuaState, skill_name.c_str(), "trigger_stage", (uint32_t&)knight_info.skills[i].triggerStage);//size_t
            
            // std::cout << knight_info.skills[i].name << " " << knight_info.skills[i].description << " " << knight_info.skills[i].triggerStage << std::endl;
        }
    }

本意只想知道上面2个malloc出错的可能,并不是一定要知道那里出错。当然,能知道更好。或者提供一个调试的方法,多谢

最近编辑记录 beginner (2020-06-02 23:21:53)

离线

#2 2020-06-03 08:26:14

xtricman
エクス·トリクマン
注册时间: 2012-12-26
帖子: 1,131

Re: malloc断言失败,大概可能是哪些原因导致?

你对问题优质不优质的判断标准是字数?


反社会,精神极其不稳定,随时可能炸碎身边所有人

离线

#3 2020-06-03 08:52:05

xtricman
エクス·トリクマン
注册时间: 2012-12-26
帖子: 1,131

Re: malloc断言失败,大概可能是哪些原因导致?

标准文档没有谈及malloc会abort,你abort的位置全部都在libc的malloc函数内,疑似libc有bug,换之测试

最近编辑记录 xtricman (2020-06-03 08:52:48)


反社会,精神极其不稳定,随时可能炸碎身边所有人

离线

#4 2020-06-03 11:35:54

依云
性别女,请正确称呼
所在地: a.k.a. 百合仙子
注册时间: 2011-08-21
帖子: 5,663
个人网站

Re: malloc断言失败,大概可能是哪些原因导致?

beginner 说:

本意只想知道上面2个malloc出错的可能,并不是一定要知道那里出错。当然,能知道更好。或者提供一个调试的方法,多谢

你内存写越界,把分配器的数据覆盖了。
valgrind 看看吧。

离线

#5 2020-06-03 13:50:51

xtricman
エクス·トリクマン
注册时间: 2012-12-26
帖子: 1,131

Re: malloc断言失败,大概可能是哪些原因导致?

依云 说:
beginner 说:

本意只想知道上面2个malloc出错的可能,并不是一定要知道那里出错。当然,能知道更好。或者提供一个调试的方法,多谢

你内存写越界,把分配器的数据覆盖了。
valgrind 看看吧。

所以glibc的malloc会做一个assert来做一个数据检查,如果查到破坏会abort?有文档说吗?我看manpage没有描述malloc会abort吧,它不返回null而是abort这个行为比较意外…


反社会,精神极其不稳定,随时可能炸碎身边所有人

离线

#6 2020-06-03 14:15:39

依云
性别女,请正确称呼
所在地: a.k.a. 百合仙子
注册时间: 2011-08-21
帖子: 5,663
个人网站

Re: malloc断言失败,大概可能是哪些原因导致?

xtricman 说:
依云 说:
beginner 说:

本意只想知道上面2个malloc出错的可能,并不是一定要知道那里出错。当然,能知道更好。或者提供一个调试的方法,多谢

你内存写越界,把分配器的数据覆盖了。
valgrind 看看吧。

所以glibc的malloc会做一个assert来做一个数据检查,如果查到破坏会abort?有文档说吗?我看manpage没有描述malloc会abort吧,它不返回null而是abort这个行为比较意外…

你都 UB 了 abort 掉一点也不奇怪啊。

离线

#7 2020-06-06 12:46:26

beginner
会员
注册时间: 2019-10-07
帖子: 144

Re: malloc断言失败,大概可能是哪些原因导致?

多谢,我已经开始用valgrind了。
不过,如果使用了valgrind后仍有不解的地方可能还会来问。

离线

页脚