Skip to content

Commit

Permalink
all: make GC opt-in via sdl_use_gc, remove -d sdl_memory_no_gc (v…
Browse files Browse the repository at this point in the history
  • Loading branch information
larpon authored Nov 24, 2024
1 parent 050cdcb commit 74367e7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 23 deletions.
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,22 @@ 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
```

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

Expand Down Expand Up @@ -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 ..
Expand Down
24 changes: 12 additions & 12 deletions c/memory.c.v
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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',
Expand All @@ -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',
Expand All @@ -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) }
}
}

Expand Down
6 changes: 3 additions & 3 deletions tests/crash_with_gc.vv
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 74367e7

Please sign in to comment.