gnustep / libobjc2

Objective-C runtime library intended for use with Clang.
http://www.gnustep.org/
MIT License
426 stars 116 forks source link

libasan detects leaks #270

Closed ghost closed 5 months ago

ghost commented 5 months ago

Hi!

We compile all binaries with the libasan, which detects several memory leaks: Sample code:

#include <Foundation/Foundation.h>

@interface Obj: NSObject
@end

@implementation Obj
@end

int main(void)
{
return 0;
}

Compile with: gcc $(gnustep-config --objc-flags --gui-libs) -fsanitize=address -lgnustep-base -lobjc test.mm -o test

Error returned:

=================================================================
==521628==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 1840 byte(s) in 115 object(s) allocated from:
    #0 0x7f18e02179cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x7f18dfabbc9c in objc_malloc (/lib/x86_64-linux-gnu/libobjc.so.4+0xac9c)

Direct leak of 40 byte(s) in 1 object(s) allocated from:
    #0 0x7f18e02179cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x7f18dfabbe4c in class_copyMethodList (/lib/x86_64-linux-gnu/libobjc.so.4+0xae4c)

Indirect leak of 6496 byte(s) in 406 object(s) allocated from:
    #0 0x7f18e02179cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0x7f18dfabbc9c in objc_malloc (/lib/x86_64-linux-gnu/libobjc.so.4+0xac9c)

SUMMARY: AddressSanitizer: 8376 byte(s) leaked in 522 allocation(s).

system: Linux NAME 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 GNU/Linux

hmelder commented 5 months ago

As you are using libs-base and NSObject as root class, you should open an issue in the libs-base GitHub repository instead.

hmelder commented 5 months ago

More information about the toolchain (libobjc2, or GCC libobjc), compiler version, linker, and libs-base version would be helpful as well.

ghost commented 5 months ago
$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/12/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 12.2.0-14' --with-bugurl=file:///usr/share/doc/gcc-12/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-12 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --enable-cet --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none=/build/gcc-12-bTRWOB/gcc-12-12.2.0/debian/tmp-nvptx/usr,amdgcn-amdhsa=/build/gcc-12-bTRWOB/gcc-12-12.2.0/debian/tmp-gcn/usr --enable-offload-defaulted --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.2.0 (Debian 12.2.0-14)
$ sudo apt list --installed | grep gnustep
WARNING: apt does not have a stable CLI interface. Use with caution in scripts.

gnustep-back-common/stable,now 0.29.0-3 amd64 [installed,automatic]
gnustep-back0.29-cairo/stable,now 0.29.0-3 amd64 [installed,automatic]
gnustep-back0.29/stable,now 0.29.0-3 all [installed,automatic]
gnustep-base-common/stable,now 1.28.1+really1.28.0-5 all [installed,automatic]
gnustep-base-doc/stable,now 1.28.1+really1.28.0-5 all [installed,automatic]
gnustep-base-runtime/stable,now 1.28.1+really1.28.0-5 amd64 [installed,automatic]
gnustep-common/stable,now 2.9.1-2 amd64 [installed,automatic]
gnustep-core-devel/stable,now 7.10 all [installed,automatic]
gnustep-core-doc/stable,now 7.10 all [installed,automatic]
gnustep-devel/stable,now 7.10 all [installed]
gnustep-gui-common/stable,now 0.29.0-2 all [installed,automatic]
gnustep-gui-doc/stable,now 0.29.0-2 all [installed,automatic]
gnustep-gui-runtime/stable,now 0.29.0-2+b3 amd64 [installed,automatic]
gnustep-icons/stable,now 1.0-10 all [installed,automatic]
gnustep-make-doc/stable,now 2.9.1-2 all [installed,automatic]
gnustep-make/stable,now 2.9.1-2 all [installed,automatic]
gnustep/stable,now 7.10 all [installed]
libgnustep-base-dev/stable,now 1.28.1+really1.28.0-5 amd64 [installed,automatic]
libgnustep-base1.28/stable,now 1.28.1+really1.28.0-5 amd64 [installed,automatic]
libgnustep-gui-dev/stable,now 0.29.0-2+b3 amd64 [installed]
libgnustep-gui0.29/stable,now 0.29.0-2+b3 amd64 [installed,automatic]

I also posted the issue here: https://github.com/gnustep/libs-base/issues/364 If you need any more information, feel free to ask.

davidchisnall commented 5 months ago

If you're compiling with GCC (which I strongly recommend against), then it will emit the ancient GCC Objective-C ABI where a large number of features will not work. We do an upgrade pass on loading, which constructs the structures for the new ABI with heap memory for all loaded classes. This will probably show up as leaked, because we never free it (it is expected to be present for the lifetime of the program and there is no benefit from calling free a bunch of times before exit).

If you compile with clang and -fobjc-runtime=gnustep-2.0 (or 2.2 if you're using trunk), then you should not see these copies.