dearimgui / dear_bindings

C header (and language binding metadata) generator for Dear ImGui
MIT License
221 stars 12 forks source link

Trying to load custom font gives segfault #65

Closed techie-guy closed 6 months ago

techie-guy commented 6 months ago

I am trying to load in a custom font(Nerd Font)

ImGui_CreateContext(NULL);
ImGuiIO* io = ImGui_GetIO();
ImVector_ImWchar ranges;
ImFontGlyphRangesBuilder builder;

// These 3 lines cause the segfault
ImFontGlyphRangesBuilder_AddRanges(&builder, ImFontAtlas_GetGlyphRangesDefault(io->Fonts));
ImFontGlyphRangesBuilder_AddText(&builder, "", NULL);
ImFontGlyphRangesBuilder_BuildRanges(&builder, &ranges);

ImFontAtlas_AddFontFromFileTTF(io->Fonts, "assets/fonts/font.ttf", 45, NULL, ranges.Data);
ImFontAtlas_Build(io->Fonts);

On Running the app, I get this:

mist-lib: imgui/imgui.h:2003: T &ImVector<unsigned int>::operator[](int) [T = unsigned int]: Assertion `i >= 0 && i < Size' failed.
zsh: IOT instruction (core dumped)  ./bin/Debug-Native/mist-lib/mist-lib

GDB Backtrace:

mist-lib: imgui/imgui.h:2003: T &ImVector<unsigned int>::operator[](int) [T = unsigned int]: Assertion `i >= 0 && i < Size' failed.

Thread 1 "mist-lib" received signal SIGABRT, Aborted.
__pthread_kill_implementation (no_tid=0, signo=6, threadid=140737344604032) at ./nptl/pthread_kill.c:44
44  ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140737344604032) at ./nptl/pthread_kill.c:44
#1  __pthread_kill_internal (signo=6, threadid=140737344604032) at ./nptl/pthread_kill.c:78
#2  __GI___pthread_kill (threadid=140737344604032, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
#3  0x00007ffff7956476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4  0x00007ffff793c7f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff793c71b in __assert_fail_base (fmt=0x7ffff7af1130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5555556e2c28 "i >= 0 && i < Size", 
    file=0x5555556e2b82 "imgui/imgui.h", line=2003, function=<optimized out>) at ./assert/assert.c:92
#6  0x00007ffff794de96 in __GI___assert_fail (assertion=0x5555556e2c28 "i >= 0 && i < Size", file=0x5555556e2b82 "imgui/imgui.h", line=2003, 
    function=0x5555556e2c85 "T &ImVector<unsigned int>::operator[](int) [T = unsigned int]") at ./assert/assert.c:101
#7  0x00005555555e9b19 in ImVector<unsigned int>::operator[](int) ()
#8  0x00005555555e91c1 in ImFontGlyphRangesBuilder::SetBit(unsigned long) ()
#9  0x00005555555e91f2 in ImFontGlyphRangesBuilder::AddChar(unsigned short) ()
#10 0x000055555567f334 in ImFontGlyphRangesBuilder::AddRanges(unsigned short const*) ()
#11 0x00005555555e768d in ImFontGlyphRangesBuilder_AddRanges ()
#12 0x000055555555acc0 in init () at src/Application.c:91
#13 0x000055555555ae69 in runApplication () at src/Application.c:146
#14 0x000055555558cc36 in main () at src/main.c:6

Am I doing anything incorrectly?

ShironekoBen commented 6 months ago

Looking at the code, I think the problem is that there's a special case here for ImVector because ImFontGlyphRangesBuilder_BuildRanges() has to be able to resize the vector it is using, resulting in memory allocated internally within ImGui (potentially using a different heap from the user code and thus causing chaos when the vector is deallocated). There are some more notes in the Readme.md file about this (see the section on "Constructors/destructors"), but I think that the code above can probably be fixed by adding the three commented lines here:

ImGui_CreateContext(NULL);
ImGuiIO* io = ImGui_GetIO();
ImVector_ImWchar ranges;
ImVector_Construct(&ranges); // Construct the vector
ImFontGlyphRangesBuilder builder;
memset(&builder, 0, sizeof(builder)); // Probably not related to the current issue but recommended if you don't have compiler flags set to guarantee zero-initialisation

ImFontGlyphRangesBuilder_Clear(&builder);
ImFontGlyphRangesBuilder_AddRanges(&builder, ImFontAtlas_GetGlyphRangesDefault(io->Fonts));
ImFontGlyphRangesBuilder_AddText(&builder, "", NULL);
ImFontGlyphRangesBuilder_BuildRanges(&builder, &ranges);

ImFontAtlas_AddFontFromFileTTF(io->Fonts, "assets/fonts/font.ttf", 45, NULL, ranges.Data);
ImFontAtlas_Build(io->Fonts);

ImVector_Destruct(&ranges); // Free the vector using ImGui's heap functions

Hopefully that helps - if it doesn't then let me know and I'll dig a bit deeper!

techie-guy commented 6 months ago

It worked, Thanks!