LWJGL Forum

Programming => Bug Reports / RFE => Topic started by: orange451 on January 25, 2018, 23:24:43

Title: [Bug] Cannot free Yoga Node on Mac OS
Post by: orange451 on January 25, 2018, 23:24:43
Trying to use Yoga with lwjgl. If I run this code:
long a =  Yoga.YGNodeNew();
Yoga.YGNodeFree(a);


The 2nd line (freeing the memory) crashes the JVM.

Here's a copy of the crash report:
https://pastebin.com/yMKngwC2
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: spasi on January 26, 2018, 07:34:27
Does it work if you run it with -Dorg.lwjgl.system.allocator=system?

Also, how do you launch the application? (IDE? terminal?)
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: orange451 on January 26, 2018, 17:55:03
Adding -Dorg.lwjgl.system.allocator=system fixes the problem

Thanks.
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: CoDi on January 26, 2018, 21:29:12
This doesn't fix the problem, just hides it.

I believe this is a bug in Yoga:

https://github.com/facebook/yoga/blob/master/yoga/Yoga.cpp#L218
https://github.com/facebook/yoga/blob/master/yoga/Yoga.cpp#L259

Matching new and free is undefined behavior, as far as I remember. The MacOS system allocator may just get over it silently.
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: spasi on January 27, 2018, 00:26:10
Good catch CoDi! Indeed, using delete instead of free fixes the crash for me.

But now I'm curious why using -Dorg.lwjgl.system.allocator=system makes a difference. Yoga does not use the LWJGL allocator (which is jemalloc on macOS by default), in any way.
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: CoDi on January 27, 2018, 01:05:01
Well, it looks like jemalloc "simply" hooks into the stdlib functions, so the free() call goes through jemalloc. I have no idea how the default operator new is wired internally to do the actual allocation.
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: orange451 on January 27, 2018, 02:07:39
So to clarify, what is the "correct" way of handling this?
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: spasi on January 27, 2018, 08:23:40
Quote from: orange451 on January 27, 2018, 02:07:39So to clarify, what is the "correct" way of handling this?

The next 3.1.6 snapshot (build 12) will have a modified Yoga with delete instead of free, so hopefully you won't have to do anything.
Title: Re: [Bug] Cannot free Yoga Node on Mac OS
Post by: spasi on January 27, 2018, 12:29:49
Quote from: CoDi on January 27, 2018, 01:05:01Well, it looks like jemalloc "simply" hooks into the stdlib functions, so the free() call goes through jemalloc. I have no idea how the default operator new is wired internally to do the actual allocation.

I've had a better look at this, because the jemalloc build that comes with LWJGL is built with `--disable-zone-allocator`, which means it does not replace the default macOS allocator.

Turns out it does override C++ new/delete with jemalloc_cpp.cpp (https://github.com/jemalloc/jemalloc/blob/3f5049340e66c6929c3270f7359617f62e053b11/src/jemalloc_cpp.cpp). So with the way jemalloc is built, YGNodeNew goes to je_malloc via the overridden new, but YGNodeFree goes to the default zone allocator's free. Which tries to free a pointer it doesn't know about and crashes.

I couldn't believe you can override new/delete by loading a shared library without something like LD_PRELOAD, but apparently it's actually possible (https://developer.apple.com/library/content/technotes/tn2185/_index.html#//apple_ref/doc/uid/DTS10004200-CH1-SECTION13) on macOS.

Build 12 will include both the Yoga fix and a jemalloc built with `--disable-cxx --disable-zone-allocator` (i.e. neither the default zone allocator, nor new/delete will be overridden).