malloc内存申请--释放-收缩

 一、验证思路和代码

#include <stdio.h>
#include <unistd.h>
#include <malloc.h>
#include <stdlib.h>
#include <sys/mman.h>

#define PAGE_SIZE getpagesize()
#define THRESHOLD 32
#define MALLOC_SIZE 20
#define HEAD_SIZE 0x10

int main(int argc, char *argv[])
{
    //sbrk(0) 函数用于返回堆顶指针
    printf("PAGE_SIZE: %d
", PAGE_SIZE);
    #if 1
    int ret = mallopt(M_TRIM_THRESHOLD,  THRESHOLD * PAGE_SIZE); //门限设为128K 
    if(0 == ret)
    {
        printf("mallopt err, ret: %d
", ret);
        return -1;
    }
    #endif
    /*第一阶段*/
    char *temp = (char*)sbrk(0);
    printf("A: heap init addr: %p
", temp);
    sleep(20);//观察vss, rss, pss, uss 并记录vss1:;rss1, pss1, uss1
    char *p1 = (char*)malloc(MALLOC_SIZE * PAGE_SIZE - 2 * HEAD_SIZE);
    printf("B: heap init addr: %p, page num: %d
", sbrk(0),  ((long)sbrk(0) - (long)temp) / PAGE_SIZE); //预期:sbrk(0)增大 MALLOC_SIZE*PAGE_SIZE
    printf("C: p1 = %p
", p1);
    /*第二阶段*/
    sleep(20);//观察vss, rss, pss, uss 预期vss2=vss1+MALLOC_SIZE*PAGE_SIZE, rss2=rss1, pss2=pss1,uss2=uss1
    /*第三阶段*/
    for(int i = 0; i < MALLOC_SIZE; i++)
    {
        p1[i * PAGE_SIZE + i] = 'a' + i;
        sleep(1);//观察vss, rss, pss, uss 预期vssi=vss1+MALLOC_SIZE*PAGE_SIZE, 
                       //rssi=rss(i-1) + PAGE_SIZE, pss2i=pss(i-1) + PAGE_SIZE,ussi=uss(i-1) + PAGE_SIZE
    }
    
    printf("D: heap init addr: %p
", sbrk(0));//预期sbrk不变
    
    /*第四阶段*/
    //char *p2 = (char*)sbrk(0);
    sleep(2);
    char *p3 = (char*)malloc(MALLOC_SIZE * PAGE_SIZE  - 2 * HEAD_SIZE);
    for(int i = 0; i < MALLOC_SIZE; i++)
    {
        p1[i * PAGE_SIZE + i] = 'a' + i;
        sleep(1);//观察vss, rss, pss, uss 预期vssi=vss2+MALLOC_SIZE*PAGE_SIZE, 
                       //rss3i=rss3(i-1) + PAGE_SIZE, pss3i=pss3(i-1) + PAGE_SIZE,uss3i=uss3(i-1) + PAGE_SIZE
    }
    printf("E: heap init addr: %p
", sbrk(0)); //预期:sbrk(0)增大MALLOC_SIZE * PAGE_SIZE
    
    /*第五阶段*/
    free(p1);
    printf("F: heap init addr: %p
", sbrk(0));//预期sbrk(0)不变
    /*free释放内存后,因为该内存区域形成空洞,并且空闲内存没有达到内存收缩门限,所以没有还给内核,libc继续做二级管理;
    所以还可以访问,不合规范,只做演示*/
    printf("
");
    for(int i = 0; i < MALLOC_SIZE; i++)
    {
        if(i % 3 == 0)
        {
            printf("
");
        }
        printf("p1[i * PAGE_SIZE + i]: %c  ", p1[i * PAGE_SIZE + i]);
    }
    printf("
");
    
    /*第六阶段*/
    free(p3);
    printf("G: heap init addr: %p
", sbrk(0)); //预期:sbrk(0)减小 THRESHOLD
    sleep(20);//观察vss, rss, pss, uss 预期 减小128K,不会恢复到第一次观察到的值,因为libc没有完全把内存还给系统
    
    return 0;
}

二、运行结果

1、在64位机子上跑打印:

 1 [root@localhost ]# ./malloc_free.o 
 2 PAGE_SIZE: 4096
 3 A: heap init addr: 0xf7d000
 4 B: heap init addr: 0xfb2000, page num: 53
 5 C: p1 = 0xf7d010
 6 D: heap init addr: 0xfb2000
 7 E: heap init addr: 0xfb2000
 8 F: heap init addr: 0xfb2000
 9 
10 
11 p1[i * PAGE_SIZE + i]: ? p1[i * PAGE_SIZE + i]: b  p1[i * PAGE_SIZE + i]: c  
12 p1[i * PAGE_SIZE + i]: d  p1[i * PAGE_SIZE + i]: e  p1[i * PAGE_SIZE + i]: f  
13 p1[i * PAGE_SIZE + i]: g  p1[i * PAGE_SIZE + i]: h  p1[i * PAGE_SIZE + i]: i  
14 p1[i * PAGE_SIZE + i]: j  p1[i * PAGE_SIZE + i]: k  p1[i * PAGE_SIZE + i]: l  
15 p1[i * PAGE_SIZE + i]: m  p1[i * PAGE_SIZE + i]: n  p1[i * PAGE_SIZE + i]: o  
16 p1[i * PAGE_SIZE + i]: p  p1[i * PAGE_SIZE + i]: q  p1[i * PAGE_SIZE + i]: r  
17 p1[i * PAGE_SIZE + i]: s  p1[i * PAGE_SIZE + i]: t  
18 G: heap init addr: 0xf9e000

2、观察:

第一阶段:

三、结论

1、通过观察

原文地址:https://www.cnblogs.com/shihuvini/p/8403758.html