最近,我在调试程序时遇到了一个奇怪的错误.我们分配一个大缓冲区.释放后,内存没有返回操作系统.然后由于内存不足,以下分配可能会失败.然后我做了以下测试程序.我为指针c分配了内存,并没有释放它来模拟我的真实程序. (在我的程序中,OpenMPI调用导致内存泄漏很少.)
由于内存不足,它将在计算机(Mac)的第18行失败,可用内存为3 GB.我知道指针c会导致内存碎片.但是对于像a和b这样的大内存缓冲区,它们是由mmap而不是brk分配的.它们应该可以直接释放,对吧?我该怎么做才能解决这个问题?
#include <stdlib.h>
#include <string.h>
int main(){
float *a=malloc(1250000000);
memset(a, (char)1, 1250000000);
float *b=malloc(1250000000);
memset(b, (char)1, 1250000000);
float *c=malloc(10);
memset(c, (char)1, 10);
free(b);
free(a);
float *d=malloc(2000000000); /* FAILS HERE */
memset(d, (char)1, 2000000000);
}
最佳答案 您在评论中提到您正在观察Mac下程序的行为.假设您的意思是操作系统X,那么您的程序的行为并不像您认为的那样.分配器为每个calloc调用执行mmap调用,并且空闲调用不会导致munmap,因为分配器期望重用您分配的内存.
这可以通过使用dtruss来验证:
$dtruss -f -t mmap ./a.out
PID/THRD SYSCALL(args) = return
57843/0x16bf38: mmap(0x10C119000, 0x2000, 0x5, 0x12, 0x3, 0x1000) = 0x10C119000 0
57843/0x16bf38: mmap(0x10C11B000, 0x1000, 0x3, 0x12, 0x3, 0x3000) = 0x10C11B000 0
57843/0x16bf38: mmap(0x10C11C000, 0x1FC0, 0x1, 0x12, 0x3, 0x4000) = 0x10C11C000 0
$
注意三次调用mmap.但是,没有调用brk或sbrk,也没有调用munmap:
$dtruss -f -t brk ./a.out
PID/THRD SYSCALL(args) = return
$dtruss -f -t sbrk ./a.out
PID/THRD SYSCALL(args) = return
$dtruss -f -t munmap ./a.out
PID/THRD SYSCALL(args) = return
$