April 24, 2024

Unit Test Memory Leak with A̶s̶s̶a̶m̶ Asan

Unit Test Memory Leak with A̶s̶s̶a̶m̶ Asan

This is the follow up for the previous post.

To detect memory leak in the golang code, we can utilize the memory error detector, Asan., which is used by my team to verify the fix.

A little quirk here - if the main function is in go, we have to do some wiring manually.

//go:build asan

package memory_leak

/*

void __lsan_do_leak_check(void);

*/

import "C"

func checkLeak() {
	C.__lsan_do_leak_check()
}

asan.go

Seems it's related to how the go main function registers the library call in the beginning. I don't fully understand it, but this is the only post I found:

sanitizer-leak is NOT detected when golang using cgo to call c library
Summary Previously I used clang-3.8.1 and sanitizer is crashed when using AddressSanitizer. And leakSanitizer doesn’t work at all. Then I try to use clang-llvm-10.0, AddressSanitizer could detect…

To invoke the checker, we should run it in TestMain so that the it runs in the main go routine and detects the memory leak for all the test functions

package memory_leak

func TestSomething(t *testing.T){

}

func TestMain(m *testing.M) {
	m.Run()
	checkLeak()
}

memory_leak_test.go

Here are the flags for the Asan, the team uses the following command to run the test, where report_globals=0 denotes we don't detect buffer overflow on globals.

ASAN_OPTIONS=report_globals=0 go test --tags -asan ./pkg/memory_leak

If a leak is detected, the result would look like the following log

=================================================================
==51300==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 66 byte(s) in 1 object(s) allocated from:
    #0 0x7b9fe325b9a7 in __interceptor_strdup ../../../../src/libsanitizer/asan/asan_interceptors.cpp:454
    #1 0x18492a3  (/tmp/go-build3263339893/b001/memory_leak.test+0x18492a3)

SUMMARY: AddressSanitizer: 66 byte(s) leaked in 1 allocation(s).