emscripten-core / emscripten-core/emscripten

Memory leak in class function

Open
#21,709 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
27.6k
Forks
3.6k
Avg merge
1d 1h
Merged PRs (30d)
105

Description

I've been encountering into memory leak when I use class function binding.
Despite I explicitly called `delete()` function, the memory leak is still happening at `doLeackCheck()`.

As far as my looking, the situation happens from `bind.h`:
```cpp
// TODO: This could do a reinterpret-cast if sizeof(T) === sizeof(void*)
template
inline T* getContext(const T& t) {
// not a leak because this is called once per binding
auto* ret = new T(t);
#if __has_feature(leak_sanitizer) || __has_feature(address_sanitizer)
__lsan_ignore_object(ret);
#endif
return ret;
}
```

I'm wondering this is real leak because I see the comment `not a leak because this is called once per binding`. However the leak sanitizer still addresses this as memory leak, and seems not to be freed even after `delete()` called.

I attach addr2line output in where sanitizer points:
```
wasm-tools addr2line -v test-wasm.wasm 0x150e8

0x150e8: void (Test::**)() emscripten::internal::getContext(void (Test::* const&)()) /Users/jinny/Dev/emsdk/upstream/emscripten/cache/sysroot/include/emscripten/bind.h:718:17
void emscripten::internal::RegisterClassMethod::invoke(char const*, void (Test::*)()) /Users/jinny/Dev/emsdk/upstream/emscripten/cache/sysroot/include/emscripten/bind.h:1448:13
emscripten::class_ const& emscripten::class_::function(char const*, void (Test::*)(), ) const /Users/jinny/Dev/emsdk/upstream/emscripten/cache/sysroot/include/emscripten/bind.h:1725:9
embind_init_test_bindings() /Users/jinny/Work/jinny/emc-test/build_wasm/../test.cpp:45:10
```

Appreciated if I can ensure things:
1. Should I ignore memory leak in getContext()?
2. If so, Isn't it really leaking memory? and why not ignored by `__lsan_ignore_object`?
3. In case this is real leak, hoping it's going to be resolved.

**Version of emscripten/emsdk:**
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.56-git
clang version 19.0.0git
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /opt/homebrew/Cellar/emscripten/3.1.56/libexec/llvm/bin
```

**Full link command and output with `-v` appended:**
I've tried in meson/ninja build system. It would be better if you can refer to the repro repo here:
https://github.com/tinyjin/wasm-emscripten-leak

```
The Meson build system
Version: 1.3.2
Source dir: /Users/jinny/Work/jinny/emc-test
Build dir: /Users/jinny/Work/jinny/emc-test/build_wasm
Build type: cross build
Project name: test
Project version: 0.0.1
C++ compiler for the host machine: /Users/jinny/Dev/emsdk/upstream/emscripten/em++.py (emscripten 3.1.56 "emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.56 (cf90417346b78455089e64eb909d71d091ecc055)")
C++ linker for the host machine: /Users/jinny/Dev/emsdk/upstream/emscripten/em++.py ld.wasm 19.0.0
C++ compiler for the build machine: c++ (clang 15.0.0 "Apple clang version 15.0.0 (clang-1500.3.9.4)")
C++ linker for the build machine: c++ ld64 1053.12
Build machine cpu family: aarch64
Build machine cpu: aarch64
Host machine cpu family: x86
Host machine cpu: i686
Target machine cpu family: x86
Target machine cpu: i686
Build targets in project: 1

test 0.0.1

User defined options
Cross files : /tmp/.cross.txt
default_library: static

Found ninja-1.11.1 at /opt/homebrew/bin/ninja
WARNING: Running the setup command as `meson [options]` instead of `meson setup [options]` is ambiguous and deprecated.
ninja: Entering directory `build_wasm/'
[2/2] Linking target test-wasm.js
em++: warning: -sERROR_ON_UNDEFINED_SYMBOLS specified multiple times. Ignoring previous value (`1`) [-Wunused-command-line-argument]
em++: warning: running limited binaryen optimizations because DWARF info requested (or indirectly required) [-Wlimited-postlink-optimizations]
-rwxr-xr-x 1 jinny staff 1779064 Apr 6 12:04 build_wasm/test-wasm.wasm
-rw-r--r-- 1 jinny staff 206880 Apr 6 12:04 build_wasm/test-wasm.js
```

Then If I try run this module in JS, 8 bytes direct leak occurred in each class function binding:
```
Direct leak of 8 byte(s) in 1 object(s) allocated from:
put_char @ test-wasm.js:1408
test-wasm.js:1408 #0 0x5075 in operator new(unsigned long)+0x5075 (http://0.0.0.0:4000/build_wasm/test-wasm.wasm+0x5075)
put_char @ test-wasm.js:1408
test-wasm.js:1408 #1 0x15144 in embind_init_test_bindings()+0x15144 (http://0.0.0.0:4000/build_wasm/test-wasm.wasm+0x15144)
put_char @ test-wasm.js:1408
test-wasm.js:1408 #2 0x15053 in _GLOBAL__sub_I_test.cpp+0x15053 (http://0.0.0.0:4000/build_wasm/test-wasm.wasm+0x15053)
put_char @ test-wasm.js:1408
test-wasm.js:1408 #3 0x9d8 in __wasm_call_ctors+0x9d8 (http://0.0.0.0:4000/build_wasm/test-wasm.wasm+0x9d8)
put_char @ test-wasm.js:1408
test-wasm.js:1408 #4 0x800003b0 in callRuntimeCallbacks http://0.0.0.0:4000/build_wasm/test-wasm.js:944:26
put_char @ test-wasm.js:1408
test-wasm.js:1408 #5 0x8000016b in initRuntime http://0.0.0.0:4000/build_wasm/test-wasm.js:363:3
put_char @ test-wasm.js:1408
test-wasm.js:1408 #6 0x80001729 in doRun http://0.0.0.0:4000/build_wasm/test-wasm.js:5929:5
put_char @ test-wasm.js:1408
test-wasm.js:1408
put_char @ test-wasm.js:1408

SUMMARY: LeakSanitizer: 32 byte(s) leaked in 4 allocation(s).
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.