[Model editing] Failed allocations raise C++ exceptions through the C API
Intro
Hi!
I am a researcher at University of Ljubljana, I use MuJoCo for different things.
My setup
MuJoCo 3.13.0; C API (C++ code), x84, Fedora 44.
What's happening? What did you expect?
Model editing functions, such as mjs_addBody, don't provide an option to catch failed allocations and just segment fault when the returned pointer is supposed to be NULL.
This happens because the C API functions call C++ model-editing related code that seems to rely on throwing exceptions to indicate memory-allocation failure.
I know this is an edge case that can happen on fairly large number of items (or memory-constrained environments), but I'd still like to have an option in the API to control it, instead of just segment faulting due to C++'s exceptions trying to go through C (and in my case Rust) code.
Steps for reproduction
- Compile the below code with
gcc -O0 -std=c23 -I mujoco-3.13.0/include -I mujoco-3.13.0/include/mujoco main.c -o ./crash_mujoco -L mujoco-3.13.0/lib -lmujoco -Wl,-rpath,$PWD/mujoco-3.13.0/lib - Run the code.
Minimal model for reproduction
Not relevant. The bug is in model-editing (procedural generation) .
Code required for reproduction
In this "minimal" example, malloc is overridden with an implementation that will return NULL after the first mjs_addBody call, for the purpose of demonstration.
#include <stdio.h>
#include <stdint.h>
#include "mujoco.h"
// Real allocator
void* __libc_malloc(size_t size);
// Override malloc.
static size_t total = 0;
static size_t limit = UINT32_MAX;
void* malloc(size_t size) {
if (total + size >= limit) {
return NULL;
}
total += size;
return __libc_malloc(size);
}
int main() {
mjSpec* spec = mj_makeSpec();
mjsBody* world = mjs_findBody(spec, "world");
for (long i = 1;; i++) {
mjsBody* body = mjs_addBody(world, NULL);
printf("Added bodies: %ld\n", i);
// Hack to deterministically fail malloc.
limit = total; // Force limit to the current size
//////////////////////////////////////////////////////
if (body == NULL) {
printf("mjs_addBody returned NULL at body %ld\n", i);
return 0;
}
}
}Confirmations
- I searched the latest documentation thoroughly before posting.
- I searched previous Issues and Discussions, I am certain this has not been raised before.
Source: google-deepmind/mujoco