为什么没有释放分配了malloc的虚拟内存?

时间:2016-08-11 18:23:18

标签: c unix memory hp-ux

鉴于此C程序打印私有虚拟内存:

#include <stdio.h>
#include <stdlib.h>

#define _PSTAT64 
#include <sys/param.h> 
#include <sys/pstat.h> 
#include <sys/unistd.h> 

void pstatvm() 
{ 
    struct pst_vm_status pst; 
    int idx, count; 
    long long shared_vm = 0; 
    long long shared_ram = 0; 
    long long private_vm = 0; 
    long long private_ram = 0; 

    pid_t  pid = getpid();
    idx=0; 
    count = pstat_getprocvm(&pst, sizeof(pst), (size_t)pid, idx); 
    while (count > 0) { 
    switch ((long)pst.pst_type) { 
        case PS_IO: break; 
                        /* Don't count IO space. It really is not RAM or swap. */ 
        default: 
            if (pst.pst_flags & PS_SHARED) { 
                shared_vm += (long long) pst.pst_length; 
                shared_ram += (long long)pst.pst_phys_pages; 
            } else { 
                private_vm += (long long) pst.pst_length; 
                private_ram += (long long)pst.pst_phys_pages; 
            } 
                    break; 
    } 

    idx++; 
    count = pstat_getprocvm(&pst, sizeof(pst), (size_t)pid, idx); 
    } 
    printf("%d\t\t", pid); 
    printf("%lldK\t\t", shared_vm*4); 
    printf("%lldK\t\t", shared_ram*4); 
    printf("%lldK\t\t", private_vm*4); 
    printf("%lldK\n", private_ram*4); 
} 



int main()
{
    void *p=NULL;
    int cont = 1;

    printf("pid\t\tshared_vm\tshared_ram\tprivate_vm\tprivate_ram\n"); 

     while(cont < 100)
    {
        p = malloc((cont*10)*1024*1024);
        if (p == NULL)
        {
            printf("exit\n");
            exit(1);
        }
        pstatvm();
        free(p); p=NULL;
        sleep(1);
        cont += 10;
    }

    printf ("\n\n");
    cont = 0;
    while(cont < 10)
    {
        sleep(100);
        pstatvm();
        ++cont;
    }

}

为什么private_vm没有被OS发布?

pid             shared_vm       shared_ram      private_vm      private_ram
8988            3436K           2432K           26880K          320K
8988            3436K           2432K           129280K         336K
8988            3436K           2432K           231680K         352K
8988            3436K           2432K           334080K         368K
8988            3436K           2432K           436480K         384K
8988            3436K           2432K           538880K         400K
8988            3436K           2432K           641280K         416K
8988            3436K           2432K           743680K         432K
8988            3436K           2432K           846080K         448K
8988            3436K           2432K           948480K         464K


8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K
8988            3436K           2432K           948480K         464K

来自http://www.linuxforums.org/forum/programming-scripting/153369-solved-where-does-memory-allocated-malloc-actually-come.html

  

在Linux / Unix中,所有应用程序内存都是虚拟的,除非将其换成光盘,否则它指向物理内存中的某个位置。每个页面都可以单独寻址,因此当您的应用程序堆(使用malloc()分配的内存)对您的应用程序显示为连续时,它实际上可能遍布您的物理RAM

2 个答案:

答案 0 :(得分:4)

如果要分配大的内存区域,以便在应用程序不再需要它们时真正释放它们,那么直接使用POSIX mmapmunmap函数,而不是依赖于行为足够大的malloc个请求被转换为mmap

这可能是GNU C库在GNU / Linux上的工作方式,但它不是标准定义的要求,因此期望不可移植。

显然,HP-UX系统的malloc保留了即使是大型分配的底层存储。 但是,请注意VM大小的增量大约为100 Mb 。这表明分配器正在重用先前释放的内存,从而避免了碎片。也就是说,当你释放300 Mb块然后分配400 Mb时,它不会保留原来的300 Mb,然后分配一个全新的400 Mb块;它意识到之前释放的300 Mb空间可以扩展。在分配器中可能存在其他隐藏策略,您的程序的分配模式没有演示。 我们从您的程序中得知的是,当我们进行单个大型分配然后释放它时,分配器能够保留它并扩展它以满足更大的分配请求。这不是证明分配器始终保持释放的大量分配;它可能只是针对这种情况的优化(也许是为了支持重复的realloc)。

答案 1 :(得分:3)

malloc()free()没有义务分配/解除分配虚拟内存。他们应付堆。而且,如果需要malloc()使用sbrk()来扩大堆,free()不会缩回堆,因此分配的虚拟内存量与{{1}之后的相同}。