跳至主要內容

基础组件设计

LincZero大约 2 分钟

基础组件设计

手撕线程池以及线程池性能优化分析

内存池与网络的结合,nginx有哪些不一样的处理

内存泄露检测

2个方案,项目中遇到内存泄漏不用慌

内存泄露问题

通常是作为C/C++程序员会遇到的一个问题(其他语言也有但不是重点)

  • malloc、free;new、delete
  • 日志打印

内存泄露问题

  1. 确定是否有内存泄露
    • htop猜测有内存泄露
  2. 确定在哪个地方有内存泄露

一些自动检测内存泄露的工具,可能也是下面这些原理。但会更高级,可能有些优化,例如还能知道哪些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