• 《Linux/Unix系统编程手册》读书笔记4


    《Linux/Unix系统编程手册》读书笔记 目录

    第7章:

    内存分配

    通过增加堆的大小分配内存,通过提升program break位置的高度来分配内存。

    基本学过C语言的都用过malloc来分配内存,而malloc都基于brk()和sbrk()。

    1 #include <unistd.h>
    2 
    3 int brk(void *end_data_segment);
    4 
    5 int *sbrk(intptr_t increment);

    brk()系统调用会将program break设置为end_data_segment的位置。成功调用返回0,失败返回-1。

    sbrk()系统调用会将program break原来的位置增加increment的大小。成功调用返回原来program break的位置,失败返回(void *)-1。

    PS:sbrk(0)返回program break的当前位置。

    malloc()函数,C使用该函数在堆上分配和释放内存。

    1 #include <stdlib.h>
    2 
    3 void *malloc(size_t size);

    malloc分配size字节大小的内存。并返回指向新分配的内存的起始位置的指针,该内存未经初始化;失败返回NULL。

    通常对返回的指针进行显式类型转换来获得自己想要的类型的指针。

    实际上每次调用malloc分配内存时,会额外分配多几个字节来记录这块内存的大小。(如下图所示)

    free()函数用来释放内存块。

    1 #include <stdlib.h>
    2 
    3 void free(void *ptr);

    free释放ptr指向的内存块,ptr必须是malloc、calloc、realloc返回的指针。

    free不会降低program break的位置,而是将该内存添加到空闲内存列表,用于以后malloc使用。

    PS:不能对已经调用过free函数的指针,再次调用free,这样会产生错误。

     因为malloc分配后的内存会有内存块的长度,所以free会知道这块内存的大小,从而准确的将内存块释放,并放入空闲内存块列表中。

    PS:因此不能用free随便释放不是malloc返回的指针。

    经过free释放后的内存块结构如下:

    其实malloc调用是先查找空闲内存块列表,找到合适的内存块。如果找不到合适的内存块就调用sbrk()来分配更多的内存,为了减少调用sbrk的次数,会分配比size大小更多的内存来增加program break的位置,超出size大小的内存块会放到空闲内存列表。

    calloc()函数可以对一组相同的对象分配内存。

    #include <stdlib.h>
    
    void *calloc(size_t numitems, size_t size);

    numitems指定了对象的数量,size指定了每个对象的大小。成功调用返回内存块的起始地址,失败返回NULL。malloc返回的内存不会初始化,而calloc返回的内存块是已初始化。

    realloc()函数可以调整一块内存的大小。

    1 #include <stdlib.h>
    2 
    3 void *realloc(void *ptr, size_t size);

    ptr是需要调整大小的内存块的指针, size是所需调整大小的期望值。

    成功调用会返回指向调整后内存块的指针(位置可能不同),失败返回NULL。

    练习:

    7-1. 修改程序清单7-1中的程序,在每次执行malloc()后打印出program break的当前至。指定一个较小的内存分配尺寸来运行该程序。这将证明malloc不会在每次调用时都会调用sbrk()来调整program break的位置,而是周期性地分大块内存,并从中将小片内存返回给调用者。

    程序清单7-1:

     1 /*
     2  * =====================================================================================
     3  *
     4  *       Filename:  free_and_sbrk.c
     5  *
     6  *    Description:  
     7  *
     8  *        Version:  1.0
     9  *        Created:  2014年03月19日 11时37分09秒
    10  *       Revision:  none
    11  *       Compiler:  gcc
    12  *
    13  *         Author:  alan (), alan19920626@gmail.com
    14  *   Organization:  
    15  *
    16  * =====================================================================================
    17  */
    18 
    19 #include "tlpi_hdr.h"
    20 
    21 #define MAX_ALLOCS 1000000
    22 
    23 int main(int argc, char *argv[]){
    24     char *ptr[MAX_ALLOCS];
    25     int freeStep, freeMin, freeMax, blockSize, numAllocs, j;
    26 
    27     printf("
    ");
    28 
    29     if(argc < 3 || strcmp(argv[1], "--help") == 0)
    30         usageErr("%s num-allocs blocksize [step [min [max]]]
    ", argv[0]);
    31 
    32     numAllocs = getInt(argv[1], GN_GT_0, "num-allocs");
    33 
    34     if(numAllocs > MAX_ALLOCS)
    35         cmdLineErr("num-allocs > %d
    ", MAX_ALLOCS);
    36 
    37     blockSize = getInt(argv[2], GN_GT_0 | GN_ANY_BASE, "blocksize");
    38 
    39     freeStep = (argc > 3) ? getInt(argv[3], GN_GT_0, "step") : 1;
    40     freeMin = (argc > 4) ? getInt(argv[4], GN_GT_0, "min") : 1;
    41     freeMax = (argc > 5) ? getInt(argv[5], GN_GT_0, "max") : numAllocs;
    42 
    43     if(freeMax > numAllocs)
    44         cmdLineErr("free-max > num-allocs
    ");
    45 
    46     printf("Initial program break:          %10p
    ", sbrk(0));
    47 
    48     printf("Allocing %d*%d bytes
    ", numAllocs, blockSize);
    49 
    50     for(j = 0; j < numAllocs; j++){
    51         ptr[j] = malloc(blockSize);
    52         if(ptr[j] == NULL)
    53             errExit("malloc");
    54     }
    55 
    56     printf("Program break is now:           %10p
    ", sbrk(0));
    57 
    58     printf("Freeing blocks from %d to %d in steps of %d
    ", freeMin, freeMax, freeStep);
    59     for(j = freeMin-1; j < freeMax; j += freeStep)
    60         free(ptr[j]);
    61 
    62     printf("After free(), program break is %10p
    ", sbrk(0));
    63 
    64     exit(EXIT_SUCCESS);
    65 }
    View Code
     1 /*
     2  * =====================================================================================
     3  *
     4  *       Filename:  free_and_sbrk.c
     5  *
     6  *    Description:  
     7  *
     8  *        Version:  1.0
     9  *        Created:  2014年03月19日 11时37分09秒
    10  *       Revision:  none
    11  *       Compiler:  gcc
    12  *
    13  *         Author:  alan (), alan19920626@gmail.com
    14  *   Organization:  
    15  *
    16  * =====================================================================================
    17  */
    18 
    19 #include "tlpi_hdr.h"
    20 
    21 #define MAX_ALLOCS 1000000
    22 
    23 int main(int argc, char *argv[]){
    24     char *ptr[MAX_ALLOCS];
    25     int freeStep, freeMin, freeMax, blockSize, numAllocs, j;
    26 
    27     printf("
    ");
    28 
    29     if(argc < 3 || strcmp(argv[1], "--help") == 0)
    30         usageErr("%s num-allocs blocksize [step [min [max]]]
    ", argv[0]);
    31 
    32     numAllocs = getInt(argv[1], GN_GT_0, "num-allocs");
    33 
    34     if(numAllocs > MAX_ALLOCS)
    35         cmdLineErr("num-allocs > %d
    ", MAX_ALLOCS);
    36 
    37     blockSize = getInt(argv[2], GN_GT_0 | GN_ANY_BASE, "blocksize");
    38 
    39     freeStep = (argc > 3) ? getInt(argv[3], GN_GT_0, "step") : 1;
    40     freeMin = (argc > 4) ? getInt(argv[4], GN_GT_0, "min") : 1;
    41     freeMax = (argc > 5) ? getInt(argv[5], GN_GT_0, "max") : numAllocs;
    42 
    43     if(freeMax > numAllocs)
    44         cmdLineErr("free-max > num-allocs
    ");
    45 
    46     printf("Initial program break:          %10p
    ", sbrk(0));
    47 
    48     printf("Allocing %d*%d bytes
    ", numAllocs, blockSize);
    49 
    50     for(j = 0; j < numAllocs; j++){
    51         ptr[j] = malloc(blockSize);
    52         if(ptr[j] == NULL)
    53             errExit("malloc");
    54         printf("After malloc(), program break is: %10p
    ", sbrk(0));
    55     }
    56 
    57     printf("Program break is now:           %10p
    ", sbrk(0));
    58 
    59     printf("Freeing blocks from %d to %d in steps of %d
    ", freeMin, freeMax, freeStep);
    60     for(j = freeMin-1; j < freeMax; j += freeStep)
    61         free(ptr[j]);
    62 
    63     printf("After free(), program break is %10p
    ", sbrk(0));
    64 
    65     exit(EXIT_SUCCESS);
    66 }

    测试结果:

    lancelot@debian:~/Code/tlpi$ ./7-1 15 10 2
    
    Initial program break:           0x1913000
    Allocing 15*10 bytes
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    After malloc(), program break is:  0x1934000
    Program break is now:            0x1934000
    Freeing blocks from 1 to 15 in steps of 2
    After free(), program break is  0x1934000

    可以清楚的看得出来,内存块只是调用了一次sbrk()来改变program break的位置,分配15块10个字节的内存块,只是第一次的时候调用了sbrk分配了1000个字节的内存块,并将990个字节大小的内存块放到空闲内存块列表,供以后malloc的调用使用。。。。

  • 相关阅读:
    CQD(陈丹琦)分治 & 整体二分——专题小结
    [联赛可能考到]图论相关算法——COGS——联赛试题预测
    C++ 线段树—模板&总结
    树形动态规划(树状DP)小结
    树形动态规划(树形DP)入门问题—初探 & 训练
    哈希表(散列表),Hash表漫谈
    随机系列生成算法(随机数生成)
    什么是动态规划算法,常见的动态规划问题分析与求解
    数学之美系列二十四 -- 谈谈动态规划与如何设计动态规划算法
    owasp zap 安全审计工具 功能详解
  • 原文地址:https://www.cnblogs.com/alan-forever/p/3677385.html
Copyright © 2020-2023  润新知