码迷,mamicode.com
首页 > 其他好文 > 详细

【0005】堆与栈,四大动态内存分配函数(malloc, calloc, realloc, _recalloc),以及栈内存分配函数alloca

时间:2020-07-29 10:32:34      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:oid   main   class   自动   64bit   数据结构   差值查找   eal   说明   

首先说明一下32位和64位系统下的区别:

技术图片
void main001()
{
    int num = 20;
    int *p = #

    printf("%p \n", &p);
    printf("%d \n", sizeof(p));

    
    system("pause");
}

/*
    Name    Value                        Type
32bit    &p    0x0135f7ec{0x135f7f8{20}}        int **
    p    0x135f7f8{20}                    int *

64bit    &p    0x0000007A360FF898{0x0000007a360ff874{20}}    int **
    p    0x0000007a360ff874{20}            int *
*/
32位与64位编译器下地址的表示

    /*
        指针(地址)由编译器决定(64bit/32bit),高位编译器兼容地位编译器
        32bit操作系统的寻址能力:(指针4byte)
            0x00000000-0xFFFFFFFF    2^32=2^2*2^30 = 4G
        64bit操作系统的寻址能力:(指针8byte)
            0x0000000000000000-0xFFFFFFFFFFFFFFFF    16T

       32bitCPU与64bitCPU的本质区别:
            CPU的寻址能力
            64bitCPU能进行32bit的计算和64bit计算,32bitCPU只能进行32bit的计算

       指针的大小的决定因素:
            编译器位数
            操作系统的位数
    */

 

多线程中,每一个线程都有自己独立的栈;堆内存则是共享的,32bit堆内存最大为2G,64bit最大为1024G

栈  auto int num        自动回收,自动释放( 栈是由编译器来维护的,自动回收,自动释放,默认大小为1M,可以手动拓展栈的大小)

堆  void *p=malloc(1024)    手动分配,手动释放

技术图片
void stack(int numA)        // 函数参数属于栈
{
    int numB = 10;            // 局部变量属于栈
    printf("%p, %p \n", &numA, &numB);

    numA = 1;
    numB = 2;

    printf("\n\n\n");
}

void main003()
{
    //int num[1024 * 1024];    
    /*
        0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x000000F6826C3000).        编译器默认的保留栈大小是1M

        可以从属性页查看:Property Pages-->Configuration Properties-->Linker-->System-->Stack Reserve Size(Specifies the total stack allocation size in virtual memory.Default is 1MB.  (/STACK:reserve))

        可以改变Stack的默认值
    */


    stack(1);

    printf("\n\n\n");

    stack(1);

    printf("\n\n\n");

    system("pause");
}
栈中的变量,栈大小的手动修改方法
技术图片
void runstack(void *p)
{
    while (1)
    {
        int num[1024 * 1024];        // 自动回收,自动释放
    }
}

void main004()
{
    // 32bit堆内存最大2G
    // void *p=malloc(1024*1024);

    for (int i = 0; i < 3; i++)
    {
        _beginthread(runstack, 0, NULL);        // 多线程,每一个线程都有自己独立的栈
                                                // 堆内存则是共享的,32bit堆内存最大为2G,64bit最大为1024G
    }

    system("pause");
}
在多线程中演示栈的自动生成和自动回收
技术图片
void goheap(void *p)
{
    while (1)
    {
        malloc(1024 * 1024 * 100);    // 多线程,每一个线程都有自己独立的栈
                                // 堆内存则是共享的,32bit堆内存最大为2G,64bit最大为1024G
        Sleep(1000);
    }
}
void main005()
{
    for (int i = 0; i < 3; i++)
    {
        _beginthread(goheap, 0, NULL);
    }

    system("pause");
}
在多线程中演示堆是为多个线程共用的

 

内存中的堆、栈与数据结构中的堆、栈的区别:

  内存中的栈的大小是编译器确定的,由编译器生成的代码完成分配和释放(自动分配和释放),每个线程都有一个独立的栈

  内存中的堆,是手动管理的(手动分配、手动释放),同一个进程中的多个线程共用一个堆

  数据结构中的栈——先进后出,先进先出

  数据结构中的堆——堆的本质是一个二叉树,包括二分法查找,朗格朗日差值查找,堆排序查找极值

 

通过动态内存分配函数在堆上开辟动态内存

栈中变量的静态内存分配,静态内存,编译的时候就确定了内存的大小,自动回收,自动释放

技术图片
void main024()
{
    int a[1024 * 1024 * 100];        // 栈默认大小为1M,可以手动设置为较大的栈值

    system("pause");
}
栈中的静态内存分配

堆中的动态内存分配

技术图片
void main022()
{
    //int a[10];        // 静态内存,编译的时候就确定了内存的大小
    int n;
    scanf("%d", &n);

    int *p = malloc(n*sizeof(int));

    for (int i = 0; i < n; i++)
    {
        p[i] = i;
        printf("%d \n", p[i]);
    }

    system("pause");
}
malloc函数

堆内存的动态分配(malloc)与手动释放(free)

技术图片
void main025()        // 动态分配一维数组内存
{
    // int a[N]
    int N;
    scanf("%d", &N);

    int *p = NULL;

    p = malloc(N*sizeof(int));
    printf("%p \n", p);        // 01583BA8

    for (int i = 0; i < N; i++)
    {
        p[i] = i;
        printf("%d \n", p[i]);
    }

    free(p);        // 释放内存,只能释放一次内存,不能反复释放;分配内存之后一定要通过释放指向该分配内存的指针即释放内存,否则会导致内存泄漏
    printf("%p \n", p);        // 01583BA8
    //free(p);        // 20150421.exe has triggered a breakpoint.    当再次释放时,会触发一个断点
    p = NULL;        // 指针被释放,赋值为空
    free(p);        // free释放空指针不会出错
    free(p);
    printf("%p \n", p);    // 00000000
    
    system("pause");
}
动态分配一维数组内存
技术图片
void main026()    // 动态分配二维数组内存
{
    // int a[3][10]

    int(*p)[10] = malloc(sizeof(int) * 30);
    int num = 0;

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 10; j++)
        {
            p[i][j] = num++;
            printf("%3d", *(*(p + i) + j));
        }
        printf("\n");
    }

    free(p);

    system("pause");
}
动态分配二维数组内存
技术图片
void main028()
{
    int(*p)[3][5] = malloc(sizeof(int) * 60);        // 三维数组
    int num = 0;

    for (int i = 0; i < 4; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            for (int k = 0; k < 5; k++)
            {
                printf("%3d", p[i][j][k] = num++);
            }
            printf("\n");
        }
        printf("\n\n");
    }

    free(p);

    system("pause");
}
动态分配三维数组内存

动态内存分配函数的返回值

技术图片
// malloc 函数的返回值
void main027()
{
    //int *p = malloc(23454656577889);
    //int *p = malloc(-1);    // 分配失败,-1补码,malloc函数的参数值类型size_t是unsigned int
    //int *p = malloc(0);        // 能分配成功,但是没有实际意义
    int *p = malloc(2345);
    printf("%p \n", p);

    /*
        动态内存分配函数返回值
            分配成功:返回内存的首地址
            分配失败:返回NULL
    */

    system("pause");
}
malloc函数的返回值

技术图片

技术图片
void main009()
{
    int *pm = malloc(100);            // 分配内存(以字节为最小单位),但是不会初始化,参数为内存分配的总大小
    int *pc = calloc(25, sizeof(int));    // 会按照类型大小将所有内存初始化为0,参数1:变量的个数,参数2:变量的大小

    int *p = pc;

    printf("%p", p);

    for (int i = 0; i < 25; i++)
    {
        p[i] = i;
    }

    puts("\n");
    puts("\n");

    system("puase");
}
calloc与malloc
技术图片
void main010()
{
    /*
        realloc(parm1,parm2);    
            返回值为地址:
                拓展成功,后续地址拓展,返回值为这片内存的首地址
                拓展不成功,重新开辟内存,把原地址的数据拷贝到新地址,返回值为新内存的首地址(原内存空间free掉了,被回收了)
    */
    int *p = malloc(sizeof(int) * 10);        // 有效内存区域
    int *p_p = malloc(100);

    for (int i = 0; i < 10; i++)
    {
        p[i] = i;
    }
    printf("%p \n", p);                // 0x00e749d0 {0}


    int *px = realloc(p, 200);        
    printf("%p \n", px);    

    for (int i = 10; i < 50; i++)
    {
        px[i] = i;
    }

    puts("\n");
    system("pause");
}
realloc与malloc
技术图片
void main011()
{
    int *p = calloc(25, sizeof(int));    // 会按照类型大小将所有内存初始化为0,参数1:变量的个数,参数2:变量的大小
    printf("%p", p);

    for (int i = 0; i < 25; i++)
    {
        p[i] = i;
    }

    int *px = _recalloc(p, 50, sizeof(int));

    for (int i = 25; i < 50; i++)
    {
        px[i] = i;
    }

    puts("\n");

    system("puase");
}
calloc与_recalloc

堆上开辟连续内存

技术图片
void main003()
{
    int(*p)[4] = malloc(sizeof(int) * 12);                    // 堆上开辟内存,连续分配

    int num = 0;
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            printf("%3d,%p", p[i][j] = num++, &p[i][j]);
        }
        putchar(\n);
    }
    /*
        0,01294B30  1,01294B34  2,01294B38  3,01294B3C
        4,01294B40  5,01294B44  6,01294B48  7,01294B4C
        8,01294B50  9,01294B54 10,01294B58 11,01294B5C
    */

    system("pause");
}
开辟连续的堆内存_二维数组

堆上开辟块状的内存

技术图片
void main002()
{
    int **pp = calloc(3, 4);                // 堆上分配指针数组

    for (int i = 0; i < 3; i++)
    {
        pp[i] = malloc(sizeof(int) * 4);    // 每个指针分配内存,块状分配
    }

    int num = 0;

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            printf("%3d,%p", pp[i][j] = num++, &pp[i][j]);    
            /*
                *(*(pp+i)+j) == pp[i][j]
                *(pp+i) == pp[i]
                pp+i == &pp[i]
                *(pp+i)+j == &(pp[i][j])
            */
        }
        putchar(\n);
    }

    /*
        0,00F64B68  1,00F64B6C  2,00F64B70  3,00F64B74        分块数据模型
        4,00F649E8  5,00F649EC  6,00F649F0  7,00F649F4
        8,00F64A28  9,00F64A2C 10,00F64A30 11,00F64A34
    */

    for (int i = 0; i < 3; i++)
    {
        free(pp[i]);                // 先释放块内存
    }

    free(pp);                        // 再释放指针

    system("pause");
}
开辟块状的堆内存_二维数组

 

通过栈内存分配函数在堆上开辟静态内存

技术图片
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

/*
    栈上内存分配函数:
        alloca
    堆上内存分配函数:
        malloc
        calloc
        realloc
        recalloc
*/


static void show()
{
    int *p = alloca(sizeof(int) * 10);            // alloca是栈内分配内存的函数

    for (int i = 0; i < 10; i++)
    {
        p[i] = i;
    }


    //free(p);            栈上内存不能free
}


void main018()
{
    show();

    puts("\n\n\n");

    show();

    puts("\n\n\n");

    system("pause");
}
alloca函数在栈上分配静态内存

栈上开辟连续内存

技术图片
// 栈上开辟内存
void main001()
{
    int *p = (int[]) { 0 };                // 栈上开辟一维数组
    int a[3][4];                    // 栈上开辟二维数组
    int(*px)[4] = (int[][4]) { 0 };        // 栈上开辟二维数组
    int(*py)[3][4] = (int[][3][4]) { 0 };    // 栈上开辟三维数组

    system("pause");
}
栈上开辟连续内存
技术图片
void main004()
{
    int(*p)[4] = (int[3][4]) { 0 };            // 栈上开辟二维数组,连续分配,自动释放

    int num = 0;
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            printf("%3d,%p", p[i][j] = num++, &p[i][j]);
        }
        putchar(\n);
    }

    /*
          0,012FFA48  1,012FFA4C  2,012FFA50  3,012FFA54
          4,012FFA58  5,012FFA5C  6,012FFA60  7,012FFA64
          8,012FFA68  9,012FFA6C 10,012FFA70 11,012FFA74
    */

    system("pause");
}
开辟连续的栈内存_二维数组

【0005】堆与栈,四大动态内存分配函数(malloc, calloc, realloc, _recalloc),以及栈内存分配函数alloca

标签:oid   main   class   自动   64bit   数据结构   差值查找   eal   说明   

原文地址:https://www.cnblogs.com/ant-colonies/p/13373808.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!