基础组件设计
大约 2 分钟
基础组件设计
手撕线程池以及线程池性能优化分析
内存池与网络的结合,nginx有哪些不一样的处理
内存泄露检测
2个方案,项目中遇到内存泄漏不用慌
内存泄露问题
通常是作为C/C++程序员会遇到的一个问题(其他语言也有但不是重点)
- malloc、free;new、delete
- 日志打印
内存泄露问题
- 确定是否有内存泄露
- htop猜测有内存泄露
- 确定在哪个地方有内存泄露
一些自动检测内存泄露的工具,可能也是下面这些原理。但会更高级,可能有些优化,例如还能知道哪些malloc是全局的并不需要释放
方案一:重载malloc、free
int global_memCount = 0;
void* _malloc(size_t size, const char* filename, int line) { // man malloc 可以快速查看其原型
global_memCount++;
print("[+]%s:%d, size: %ld\n", filename, line, size);
// 可改进:每次创建时,将地址及相应的位置写入文件,释放时删除。那么最后可以知道哪的文件哪一行所创建的内存没有被释放!
}
void _free(void* ptr, const char* filename, int line) {
global_memCount--;
print("[-]%s:%d\n", filename, line);
}
#define malloc(size) _malloc(size, __FILE__, __LINE__)
#define free(ptr) _free(ptr, __FILE__, __LINE__)
局限性:
- 适用于文件比较少
- 适用于用的都是自己的函数。如果调用库后,不能比较清楚知道是自己的代码还是库的代码有内存泄露(因为宏不能替换库里的函数)
方案二:hook方法
hook方法主要使用的是:dlsym
// 步骤一:
typedef void* (*malloc_t)(size_t size);
typedef void* (*free_t)(void* ptr);
malloc_t malloc_f = NULL;
free_t free_t = NULL;
// 步骤二
int enable_malloc_hook = 1;
void* malloc(size_t size) {
if (enable_malloc_hook) {
enable_malloc_hook = 0;
void* caller = __builtin_return_address(0); // 编译器自带的一个函数,但返回的地址需要用其他工具来看在哪个文件和行数:aadr2line -f -e ./public_memleak -a
// 文件写入和记录等
enable_malloc_hook = 1;
}
return malloc_f(size);
}
void free(void* ptr) {
free_f(ptr);
}
// 步骤三
void init_hook(void) {
malloc_f = dlsym(RTLD_NEXT, "malloc"); // 原理:找到malloc函数的地址,并替换之
free_f = dlsym(RTLD_NEXT, "free");
}
dlopen、dlsym、dlerror,主机是查符号表找到函数起始地址,用新的指针替换之?
gdb
# gdb backtrace
$ gdb ./public_memleak
(gdb) b 97 # 加断点
(gdb) b 101
(gdb) b 65
(gdb) b 72
(gdb) r # 运行
(gdb) c # 单步调试
(gdb) c
(gdb) c
死锁检测
死锁检测方案,为你的项目一个小组件预防死锁
红黑树、最小堆、时间轮、跳表多种方式实现定时器
从6个方面看分布式锁实现,豁然开朗
高并发编程 - 原子操作与cpu缓存一致性
Linux服务器通信协议如何设计-xml-json-protobuf
链接到当前文件 0
没有文件链接到当前文件