I'm trying to write CMake tests to detect leaks using the leaks
command line tool that comes with XCode on macOS. I've been using LSAN with the Homebrew install of LLVM, but the run times on my M1 are 100x more than what they are on an amd64 machine.
Here's an example C source file with a memory leak:
// memory-leak.c
#include <stdlib.h>
void *p;
int main()
{
p = malloc(7);
p = 0; // The memory is leaked here.
return 0;
}
After compiling with clang memory-leak.c -o memleak
and running the leaks command leaks -quiet -atExit -- ./memleak
, the output is
% leaks -quiet -atExit -- ./memleak
Process 22773 is not debuggable. Due to security restrictions, leaks can only show or save contents of readonly memory of restricted processes.
leaks Report Version: 4.0
Process 22773: 214 nodes malloced for 12 KB
Process 22773: 1 leak for 16 total leaked bytes.
1 (16 bytes) ROOT LEAK: 0x600002970050 [16]
I want to include this process as CMake test targets. The CMakeLists.txt file is:
#CMakeLists.txt
cmake_minimum_required(VERSION 3.18)
project(memleak)
find_program(LEAKS_PATH NAMES leaks REQUIRED True)
enable_testing()
add_executable(memleak memory-leak.c)
add_test(NAME memleak COMMAND leaks -quiet -atExit -- $<TARGET_FILE:memleak>)
set_tests_properties(memleak PROPERTIES WILL_FAIL True)
The resulting test hangs indefinitely. Here's the terminal command and output.
% mkdir build && cd build && cmake .. && cmake --build . && ctest --verbose
-- The C compiler identification is AppleClang 13.1.6.13160021
-- The CXX compiler identification is AppleClang 13.1.6.13160021
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/user/leakstest/build
[ 50%] Building C object CMakeFiles/memleak.dir/memory-leak.c.o
[100%] Linking C executable memleak
[100%] Built target memleak
UpdateCTestConfiguration from :/Users/user/leakstest/build/DartConfiguration.tcl
UpdateCTestConfiguration from :/Users/user/leakstest/build/DartConfiguration.tcl
Test project /Users/user/leakstest/build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 1
Start 1: memleak
1: Test command: /usr/bin/leaks "-atExit" "--" "/Users/user/leakstest/build/memleak"
1: Test timeout computed to be: 10000000
1: Process 24942 is not debuggable. Due to security restrictions, leaks can only show or save contents of readonly memory of restricted processes.
1:
1: Process: memleak [24942]
1: Path: /Users/USER/*/memleak
1: Load Address: 0x100208000
1: Identifier: memleak
1: Version: ???
1: Code Type: ARM64
1: Platform: macOS
1: Parent Process: leaks [24941]
1:
1: Date/Time: 2022-05-17 18:38:15.553 -0500
1: Launch Time: 2022-05-17 18:38:15.282 -0500
1: OS Version: macOS 12.3.1 (21E258)
1: Report Version: 7
1: Analysis Tool: /Applications/Xcode.app/Contents/Developer/usr/bin/leaks
1: Analysis Tool Version: Xcode 13.3 (13E113)
1:
1: Physical footprint: 7233K
1: Physical footprint (peak): 7233K
1: ----
1:
1: leaks Report Version: 4.0
1: Process 24942: 214 nodes malloced for 12 KB
1: Process 24942: 1 leak for 16 total leaked bytes.
1:
1: 1 (16 bytes) ROOT LEAK: 0x600002840050 [16]
1:
The test never exits. I expect the test to pass since there's a memory leak and the CMake file specifies that the test will fail.
The output of build/ctest --verbose
shows that leaks
is picking up on the memory leak, but it seems that CTest isn't responding to leaks
returning.
I've tried using a shell script that contains exec leaks -quiet -atExit -- "$@"
in place of the command, but I get the same results.
I've also tried doing the same thing with a Meson build file and got the same result.
Is there something I'm missing?