From c6e3ae7e748a31de1bbc98814a774ee2886579ba Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 10 May 2025 09:34:20 +0900 Subject: [PATCH] doc/guides/memory.md: update the document - new API - detailed hook description - migration path from old API --- doc/guides/memory.md | 119 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 108 insertions(+), 11 deletions(-) diff --git a/doc/guides/memory.md b/doc/guides/memory.md index ac62a0482..902d741f2 100644 --- a/doc/guides/memory.md +++ b/doc/guides/memory.md @@ -2,22 +2,119 @@ # Memory Allocation -There are three methods to customize memory allocation in mruby. +In mruby, you can customize how memory is allocated in two ways: -1. Provide your own `realloc()`/`free()` -2. Redefine `mrb_default_allocf()` -3. Specify a function with `mrb_open_allocf()` +1. **Provide your own `malloc()`/`realloc()`/`free()`** +2. **Override `mrb_basic_alloc_func()`** -## Provide your own `realloc()`/`free()` +--- -On some platforms, especially on microcontrollers, the standard library may not provide `malloc()`, `realloc()`, and `free()`. In such cases, it may be necessary to define memory allocation functions for the specific platform. mruby uses `realloc()` and `free()` from the standard C library for memory management. By defining these two functions of your own, you can make mruby work. However, note the following two points: +## 1. Provide your own `malloc()`/`realloc()`/`free()` -First, `realloc(NULL, size)` behaves the same as malloc(size). Second, `free(NULL)` exits without doing anything. +On platforms without a full C standard library —such as many microcontrollers— you may need to supply your own implementations of `malloc()`, `realloc()`, and `free()`. mruby’s allocator calls directly into these functions, so replacing them lets you control **every** allocation and deallocation performed by your entire program, including any third‑party libraries you link against. -## Redefine `mrb_default_allocf()` +Keep in mind: -The only function in mruby that uses the standard C library's memory allocation functions is `mrb_default_allocf()`, defined in `allocf.c`. By defining this function within your application, you can customize the memory management of your application. +- Calling `realloc(NULL, size)` must behave like `malloc(size)`. +- Calling `free(NULL)` must be a no‑op. -## Specify a function with `mrb_open_allocf()` +Simply define these three functions in your code (or link against a library that provides them), and mruby — along with all other code in your process — will use your versions automatically. -If you want to perform different memory management for each `mrb_state` within your application, you can use the `mrb_open_allocf()` function to create the `mrb_state` structure. This allows you to specify a memory allocation function (which is compatible with `mrb_default_allocf`) for each `mrb_state`. Although this scheme is not recommended. It may become obsolete in the future, since I have never seen per mrb_state memory management use-case. +## 2. Override `mrb_basic_alloc_func()` + +Inside mruby, all of its own memory allocations go through a single function called mrb_basic_alloc_func() (formerly mrb_default_allocf()). By defining this function in your application before linking, you can intercept and handle **only** the memory operations initiated by mruby itself without affecting other libraries or parts of your program. + +```c +// Example signature: +// void* mrb_basic_alloc_func(void* ptr, size_t size); +``` + +Implement mrb_basic_alloc_func() in your code, and mruby will invoke it for every internal allocation, reallocation, and free request. + +### Expected behavior + +- `mrb_basic_alloc_func(NULL, size)` should allocate `size` bytes, just like `malloc(size)`. +- `mrb_basic_alloc_func(ptr, size)` should resize the existing block at `ptr` to `size` bytes, just like `realloc(ptr, size)`. +- `mrb_basic_alloc_func(ptr, 0)` should free the block at `ptr`, just like `free(ptr)`. + +--- + +## Summary of effects: + +- **Custom `malloc`/`realloc`/`free`**: replaces allocation behavior globally (mruby + all other code and third‑party libraries). + +- **Custom `mrb_basic_alloc_func()`**: replaces allocation behavior only for mruby’s internal use, leaving other libraries’ allocations untouched. + +## Migration note + +If you are moving from the old API: + +1. **Removal of `mrb_open_allocf()`** + + - \_Old: + + ```c + mrb_state *mrb = mrb_open_allocf(my_allocf, ud); + ``` + + - \_New: + + ```c + // No allocf parameter; set up your hook via mrb_basic_alloc_func definition. + mrb_state *mrb = mrb_open_core(); + ``` + +2. **`mrb_open_core()` takes no arguments** + + - Simply drop any allocf or user-data arguments, and redefine `mrb_basic_alloc_func` as you need. + +3. **No more `mrb_allocf` type** + + - Definitions using the `mrb_allocf` typedef can be removed; implement `mrb_basic_alloc_func()` with the signature below: + + ```c + void* mrb_basic_alloc_func(void *ptr, size_t size); + ``` + +4. **`mrb_basic_alloc_func` signature change** + + - _Old:_ + + ```c + void* mrb_default_allocf(mrb_state *mrb, void *ptr, size_t size, void *ud); + ``` + + - _New:_ + + ```c + void* mrb_basic_alloc_func(void *ptr, size_t size); + ``` + +--- + +### Code examples + +- **Old style**: + + ```c + static void* + my_allocf(mrb_state *mrb, void *ud, void *ptr, size_t size) + { + // ...custom logic... + } + + mrb_state *mrb = mrb_open_allocf(my_allocf, some_ud); + ``` + +- **New style**: + + ```c + // Define your hook before creating the state: + void* + mrb_basic_alloc_func(void *ptr, size_t size) + { + // ...custom logic... + } + + mrb_state *mrb = mrb_open_core(); + ```