undefined

jemalloc 资源

1
2
3
4
5
jemalloc 原理:https://wanghenshui.github.io/2019/05/01/jemalloc.html
源码分析:https://youjiali1995.github.io/allocator/jemalloc/
https://blog.csdn.net/txx_683/article/details/53897945
https://blog.csdn.net/txx_683/article/details/53468211
实现分析:https://www.jianshu.com/p/f1988cc08dfd

知名三方库的编译方法

一、OpenSSL 调试 debug 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
git clone https://github.com/openssl/openssl.git
cd openssl

# 安装静态库
./config --prefix=/usr/local --openssldir=/usr/local/ssl
make -j10 && sudo make install

# 安装动态库。安装动态库时增加 -d 选项,调试时使用动态库,达到跟踪代码的需求
./config -d shared --prefix=/usr/local --openssldir=/usr/local/ssl
make -j10 && sudo make install

# aarch64
# --cross-compile-prefix 交叉编译器前缀
# no-asm 不使用汇编代码。由于是交叉编译,如不使用该选项,会出现汇编指令不识别的问题,因为 openssl 默认使用的汇编指令为 x86 平台下的指令,而一般的交叉编译器使用 ARM 平台下的交叉编译器
./Configure linux-aarch64 --prefix=xxx --cross-compile-prefix=aarch64-linux-gnu- -no-asm shared --debug

二、libcurl 调试 debug 方法

1
2
3
4
5
6
7
8
https://curl.se/download/

# 使用 --enable-debug 调试的时候可以达到跟踪代码的需求
# --without-nss 是因为自带的 curl 支持的 https 是 nss 版本,不是 openssl 的,我们需要用 openssl 版本的
# 可以使用 curl -V 查看
# --with-ssl 指定 openssl 的安装位置
sudo ./configure --enable-debug --prefix=/usr/local --without-nss --with-ssl=/usr/local
sudo make && sudo make install

三、编译 libasan 库

非正规的做法

查看更多

GCC 通过 --wrap 选项使用包装函数

GCC 通过 –wrap 选项使用包装函数

对 symbol 使用包装函数,任何对 symbol 未定义的引用会被解析成 __wrap_symbol。而任何对 __real_symbol 未定义的引用会被解析成 symbol。即当一个名为 symbol 符号使用 wrap 功能时,工程中任何用到 symbol 符号的地方实际使用的是 __wrap_symbol 符号,任何用到 __real_symbol 的地方实际使用的是真正的 symbol。
注意:当 __wrap_symbol 是使用 C++ 实现时,一定要加上 extern "C"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# wrap_symbol.h
extern "C" {
void* __wrap_malloc(size_t size);
void __wrap_free(void* ptr);

void* __real_malloc(size_t size);
void __real_free(void* ptr);

int foo();
int __wrap_foo();

// c++filt: _Znwm ==> operator new(unsigned long)
void* __wrap__Znwm(unsigned long size);
// c++filt _ZdlPv ==> operator delete(void*)
void __wrap__ZdlPv(void* ptr);

void* __real__Znwm(unsigned long size);
void __real__ZdlPv(void* ptr);
} // extern "C"

# wrap_symbol.cpp
void* __wrap_malloc(size_t size) {
fprintf(stdout, "call __wrap_malloc function, size: %d\n", size);
return __real_malloc(size);
}

void __wrap_free(void* ptr) {
fprintf(stdout, "call __wrap_free function\n");
__real_free(ptr);
}

int foo() {
fprintf(stdout, "call foo function\n");
return 0;
}

int __wrap_foo() {
fprintf(stdout, "call __wrap_foo function\n");
return 0;
};

void* __wrap__Znwm(unsigned long size) {
fprintf(stdout, "call __wrap__Znwm funtcion, size: %d\n", size);
return __real__Znwm(size);
}

void __wrap__ZdlPv(void* ptr) {
fprintf(stdout, "call __wrap__ZdlPv function\n");
__real__ZdlPv(ptr);
}

测试代码

1
2
3
4
5
6
7
8
9
10
int main() {
char* p1 = (char*)malloc(4);
free(p1);

foo();

int* p2 = new int;
delete p2;
return 0;
}

查看更多

gperftools

gperftools

CpuProfile 原理:start 和 stop 的区间,用于检测 cpu 以及函数的调用。生成一个 二进制+文本(smaps) 的文件,交给 pprof 来解析

CpuProfiler 中 start 调用 EnableHandler 用于注册回调(prof_handler)。回调函数中生成具体行为,插入到 hash 中,在整体 stop 或者 flush 的时候进行计算。

触发方式:以 settimer 为基础注册调度事件,以一定方式(定期)发送某个信号;然后 sigactiion 重置对此信号的处理,以达到调用我们注册的回调函数的目的。

HeapProfiler

在 start 和 end 之间,dump 一份内存视图,进行对比两个视图。以发现是否有内存泄漏

暂定方案

查看更多