测试代码
我们使用malloc申请内存,malloc是应用空间glibc库函数,不是系统调用,并不会被strace跟踪到,对应的会跟踪到brk或者mmap系统调用,测试代码中,我们连续申请5次1k内存,看是否会触发5次brk
#include <iostream>
#include <cstring>
int main() {
const int array_size = 5;
const int malloc_size = 64*1024;
void* pointers[array_size];
for (int i = 0; i < array_size; ++i) {
pointers[i] = (void*)malloc(malloc_size);
if (pointers[i] == nullptr) {
std::cerr << "Memory allocation failed for pointer " << i << std::endl;
return 1;
}
memset(pointers[i], 0, malloc_size);
std::cout << "Pointer " << i << " allocated at: " << pointers[i] << std::endl;
}
for (int i = 0; i < array_size; ++i) {
free(pointers[i]);
pointers[i] = nullptr;
std::cout << "Pointer " << i << " memory freed." << std::endl;
}
return 0;
}
测试结果
从测试结果看,只有两次brk,第一次查询堆末端地址,第二次直接申请了132k,并没有触发5次1k的brk,原因为受glibc 内存分配器
内存管理策略影响,glibc会一次分配较多内存,形成内存池并会延迟释放,减少brk或者mmap系统调用频率,提升内存申请释放性能
brk(NULL) = 0x5e7057a98000 // 查询堆末端地址
brk(0x5e7057ab9000) = 0x5e7057ab9000 // 扩展(申请) 132K=0x5e7057ab9000-0x5e7057a98000, 4k为管理开销?
szj@bcc:~/test$ strace ./a.out
............. 省略程序启动过程.............
brk(NULL) = 0x5e7057a98000
brk(0x5e7057ab9000) = 0x5e7057ab9000
futex(0x74236662977c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}, AT_EMPTY_PATH) = 0
write(1, "Pointer 0 allocated at: 0x5e7057"..., 39Pointer 0 allocated at: 0x5e7057aa9eb0
) = 39
write(1, "Pointer 1 allocated at: 0x5e7057"..., 39Pointer 1 allocated at: 0x5e7057aaa2f0
) = 39
write(1, "Pointer 2 allocated at: 0x5e7057"..., 39Pointer 2 allocated at: 0x5e7057aaa320
) = 39
write(1, "Pointer 3 allocated at: 0x5e7057"..., 39Pointer 3 allocated at: 0x5e7057aaa350
) = 39
write(1, "Pointer 4 allocated at: 0x5e7057"..., 39Pointer 4 allocated at: 0x5e7057aaa380
) = 39
write(1, "Pointer 0 memory freed.\n", 24Pointer 0 memory freed.
) = 24
write(1, "Pointer 1 memory freed.\n", 24Pointer 1 memory freed.
) = 24
write(1, "Pointer 2 memory freed.\n", 24Pointer 2 memory freed.
) = 24
write(1, "Pointer 3 memory freed.\n", 24Pointer 3 memory freed.
) = 24
write(1, "Pointer 4 memory freed.\n", 24Pointer 4 memory freed.
) = 24
exit_group(0) = ?
+++ exited with 0 +++
修改测试代码,连续申请5次,每次64K,查看会触发几次brk
再看测试结果,申请了3次132k
brk(0x56243c74e000) = 0x56243c74e000 // 移动132k
brk(0x56243c76f000) = 0x56243c76f000 // 移动132k
brk(0x56243c790000) = 0x56243c790000 // 移动132k
brk(NULL) = 0x59b2ecc4c000
brk(0x59b2ecc6d000) = 0x59b2ecc6d000
futex(0x78695662977c, FUTEX_WAKE_PRIVATE, 2147483647) = 0
brk(0x59b2ecc8e000) = 0x59b2ecc8e000
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x2), ...}, AT_EMPTY_PATH) = 0
write(1, "Pointer 0 allocated at: 0x59b2ec"..., 39Pointer 0 allocated at: 0x59b2ecc5deb0
) = 39
write(1, "Pointer 1 allocated at: 0x59b2ec"..., 39Pointer 1 allocated at: 0x59b2ecc6e2d0
) = 39
brk(0x59b2eccaf000) = 0x59b2eccaf000
write(1, "Pointer 2 allocated at: 0x59b2ec"..., 39Pointer 2 allocated at: 0x59b2ecc7e2e0
) = 39
write(1, "Pointer 3 allocated at: 0x59b2ec"..., 39Pointer 3 allocated at: 0x59b2ecc8e2f0
) = 39
write(1, "Pointer 4 allocated at: 0x59b2ec"..., 39Pointer 4 allocated at: 0x59b2ecc9e300
) = 39
write(1, "Pointer 0 memory freed.\n", 24Pointer 0 memory freed.
) = 24
write(1, "Pointer 1 memory freed.\n", 24Pointer 1 memory freed.
) = 24
write(1, "Pointer 2 memory freed.\n", 24Pointer 2 memory freed.
) = 24
write(1, "Pointer 3 memory freed.\n", 24Pointer 3 memory freed.
) = 24
brk(0x59b2ecc8f000) = 0x59b2ecc8f000
write(1, "Pointer 4 memory freed.\n", 24Pointer 4 memory freed.
) = 24
exit_group(0) = ?
+++ exited with 0 +++