From 74367e7f00528c5a56a808c3a7130ab7c4fc7606 Mon Sep 17 00:00:00 2001 From: larpon <768942+larpon@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:59:53 +0100 Subject: [PATCH] all: make GC opt-in via `sdl_use_gc`, remove `-d sdl_memory_no_gc` (#857) --- README.md | 20 ++++++++++++-------- c/memory.c.v | 24 ++++++++++++------------ tests/crash_with_gc.vv | 6 +++--- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index b3f991cc..59142463 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,12 @@ Also note that SDL2 **is not** compatible with SDL `v1.x`. ## Notes on garbage collection and memory issues Currently, with some setups, SDL2 is known to trigger crashes when used in conjunction -with V's default garbage collector. In these cases running apps importing `sdl` with -`v run` you may experience runtime crashes and output similar to this: +with V's default garbage collector. Because of this you have to explicitly **opt-in** +to use V's garbage collection with SDL2. + +If you choose to use the garbage collector with SDL objects +(by running apps importing `sdl` with `v -d sdl_use_gc run`) +you may experience runtime crashes and output similar to this: ``` main__main: RUNTIME ERROR: invalid memory access @@ -68,9 +72,9 @@ main__main: RUNTIME ERROR: invalid memory access We are tracking the issue here: https://github.com/vlang/sdl/issues/744 -The crashes can be avoided by passing `-d sdl_memory_no_gc` when compiling V applications -that contains `import sdl` and managing SDL2's memory manually with calls to the various -`destroy` and `sdl.free/1` functions. +The crashes can be avoided by simply **not** passing `-d sdl_use_gc` and +managing memory manually with SDL's memory functions like `sdl.free/1`, `sdl.malloc/1`, +`sdl.calloc/2`, `sdl.realloc/2` and the various `create_*` and `destroy` functions. ## Support @@ -131,9 +135,9 @@ To do this, change to the root directory of the sdl module, like `cd %HOMEPATH%\.vmodules\sdl` and run `v run windows_install_dependencies.vsh`. -This will create a directory called "thirdparty" which will be used to download and extract the required libraries. -To successfully run a provided example or your own projects, the sdl dlls must be copied to the main application directory. -e.g.: +This will create a directory called "thirdparty" which will be used to download and +extract the required libraries. To successfully run a provided example or your own projects, +the sdl dlls must be copied to the main application directory. e.g.: ```bash copy thirdparty\SDL2-2.24.0\lib\x64\SDL2.dll examples\basic_window\ cd .. diff --git a/c/memory.c.v b/c/memory.c.v index bef0f020..09a4a90f 100644 --- a/c/memory.c.v +++ b/c/memory.c.v @@ -4,10 +4,10 @@ module c // that Boehm will later know how to process. The callbacks here provide such versions: fn cb_malloc_func(size usize) voidptr { mut res := unsafe { nil } - $if sdl_memory_no_gc ? { - res = unsafe { C.malloc(size) } - } $else { + $if sdl_use_gc ? { res = unsafe { malloc(int(size)) } + } $else { + res = unsafe { C.malloc(size) } } $if trace_sdl_memory ? { C.fprintf(C.stderr, c'>> sdl.c.cb_malloc_func | size: %lu | => %p\n', size, res) @@ -17,10 +17,10 @@ fn cb_malloc_func(size usize) voidptr { fn cb_calloc_func(nmemb usize, size usize) voidptr { mut res := unsafe { nil } - $if sdl_memory_no_gc ? { - res = unsafe { C.calloc(int(nmemb), int(size)) } - } $else { + $if sdl_use_gc ? { res = unsafe { vcalloc(isize(nmemb) * isize(size)) } + } $else { + res = unsafe { C.calloc(int(nmemb), int(size)) } } $if trace_sdl_memory ? { C.fprintf(C.stderr, c'>> sdl.c.cb_calloc_func | nmemb: %lu | size: %lu | => %p\n', @@ -31,10 +31,10 @@ fn cb_calloc_func(nmemb usize, size usize) voidptr { fn cb_realloc_func(mem voidptr, size usize) voidptr { mut res := unsafe { nil } - $if sdl_memory_no_gc ? { - res = unsafe { C.realloc(&u8(mem), int(size)) } - } $else { + $if sdl_use_gc ? { res = unsafe { v_realloc(&u8(mem), isize(size)) } + } $else { + res = unsafe { C.realloc(&u8(mem), int(size)) } } $if trace_sdl_memory ? { C.fprintf(C.stderr, c'>> sdl.c.cb_realloc_func | mem: %p | size: %lu | => %p\n', @@ -47,10 +47,10 @@ fn cb_free_func(mem voidptr) { $if trace_sdl_memory ? { C.fprintf(C.stderr, c'>> sdl.c.cb_free_func | mem: %p\n', mem) } - $if sdl_memory_no_gc ? { - unsafe { C.free(mem) } - } $else { + $if sdl_use_gc ? { unsafe { free(mem) } + } $else { + unsafe { C.free(mem) } } } diff --git a/tests/crash_with_gc.vv b/tests/crash_with_gc.vv index 92b1f00f..dd7fe6e3 100644 --- a/tests/crash_with_gc.vv +++ b/tests/crash_with_gc.vv @@ -1,9 +1,9 @@ // This file serves as a MRE (minimal reproducible example) of a runtime crash triggered by compiling and running -// this file with just `v run ~/.vmodules/sdl/tests/crash_with_gc.vv`. On some setups, the problem seems to be +// this file with `v -d sdl_use_gc run ~/.vmodules/sdl/tests/crash_with_gc.vv`. On some setups, the problem seems to be // memory corruption happening between actions in SDL2's memory allocations and V's default garbage collector. // Especially when a lot of heap allocations occur. // -// The example does not crash if compiled with `-d sdl_memory_no_gc`. +// The example crashes if compiled with `-d sdl_use_gc`. // See also: https://github.com/vlang/sdl/issues/744 module main @@ -53,7 +53,7 @@ fn main() { sdl.render_clear(renderer) sdl.render_present(renderer) } - println('Exiting. If this was compiled without `-d sdl_memory_no_gc`, an invalid memory access error should occur') + println('Exiting. If this was compiled with `-d sdl_use_gc`, an invalid memory access error should occur') sdl.destroy_renderer(renderer) sdl.destroy_window(window)