GO语言的内存泄露
排查Go语言内存泄露,毫无疑问的用pprof就好了,具体用法这篇文章中就不展开表述。
Cgo的内存泄露
怎么排查Cgo,网上相关的文章很少,可以使用pmap+gdb的方式来排查pmap+gdb排查内存泄露.但是这个方法太复杂了,对错误原因的提示不是特别友好。
如果使用fsanitize内存消毒来进行检测,就能很快的定位到哪个so或者哪个文件发生内存泄露,能定位到哪行代码发生了内存泄露,但是在cgo中,只能定位到某个文件某段内存是否发生内存泄露,而不能定位到具体的代码行,但是也减少了我们排查问题的时间。
排查内存泄露过程中有遇到一些坑,leak检测没有生效,原因是__lsan_do_leak_check没有在golang启动时注册,需要手动注册,参考 sanitizer-leak is not detected when golang using cgo to call c libary, 需要在代码中加上
void __lsan_do_leak_check(void);
的头文件引用
package main
// #include <stdio.h>
// #include <stdlib.h>
//
// void __lsan_do_leak_check(void);
//
// void leak_a_bit(void)
// {
// char* p = malloc(2000);
// printf("%p\n", p);
// }
import "C"
func main() {
C.leak_a_bit()
C.__lsan_do_leak_check()
}
然后编译中加上内存地址检测(可以和内存泄露共用)
CC="clang" CGO_CFLAGS="-fsanitize=address" CGO_LDFLAGS="-fsanitize=address" go run sanitizer.go
=================================================================
==30208==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x49ac9b (/tmp/go-build1793173723/b001/exe/sanitizer+0x49ac9b)
#1 0x5383fb (/tmp/go-build1793173723/b001/exe/sanitizer+0x5383fb)
#2 0x538890 (/tmp/go-build1793173723/b001/exe/sanitizer+0x538890)
#3 0x514f63 (/tmp/go-build1793173723/b001/exe/sanitizer+0x514f63)
SUMMARY: AddressSanitizer: 40 byte(s) leaked in 1 allocation(s).
exit status 23
centos中安装clang编译器
yum -y install epel-release
yum -y install clang