That's why you don't use it on small microcontrollers (8/16 bit). And if you absolutely have to, use it once on startup to implement a dynamic memory pool.
I just searched for esp32 projects/libraries on github, the first 3 had malloc calls.
Maybe they don't do[1] dynamic memory allocation in code segments that have real time constraints, or after initialization, etc. (Most embedded projects actually don't have hard real-time constraints, or have them in extremely localized places like bit banging loops...) This is sounds like a good idea and is orthogonal to whether the language's dynamic allocation support is via malloc/free or gc.
Yeah fair. But I think that any gc language for microcontrollers should have a couple features:
1) A compiler flag or similar optional static check that throws a warning if you have dynamic memory allocation. In scripting languages it can be easy to do accidentally
2) A way to block the gc from happening in a time critical section of code, like how you can disable interrupts
3) Some guarantee on the maximum time gc will take
MicroPython provides a way to stop the GC (and an exception will be raised if memory is attempted to be allocated). This provides us with most of the control we require...