动态内存管理

1.静态内存与动态内存的区别

1.1静态内存

  • 在栈区开辟
  • 出作用域时释放
  • 可管理的内存大小固定

1.2动态内存

  • 在堆区开辟
  • 释放由free函数执行:不主动释放会造成内存泄漏
  • 可管理内存的大小可变

2.创建动态内存的方式

2.1malloc创建动态内存

2.1.1函数原型

void* malloc(size_t size);

2.1.2函数功能

  • 在堆区开辟一块连续的size字节的空间,如果开辟成功,返回首地址;开辟失败,返回NULL指针;

2.1.3注意事项

  • 返回值为void*,因此需要使用者强制类型转换为指定类型
  • 如果size = 0,行为标准未定义,由编译器决定
  • malloc函数不初始化

2.2calloc创建动态内存

2.2.1函数原型

void* calloc(size_t num, size_t size);

  • num:开辟的元素个数
  • size:每个元素的字节大小

2.2.2函数功能

  • 在堆区创建一块大小为num*size字节的连续的内存空间

2.2.3注意事项

  • 返回值为void*, 因此需要使用者强制类型转换为指定类型
  • 如果参数为0,则标准未定义,由编译器决定
  • calloc函数会初始化指定空间为0

2.2.4malloc与calloc的区别

  1. 函数参数
  2. calloc函数会初始化

2.2.5总结

  • 什么时候用malloc与calloc函数,决定空间是否初始化

2.3realloc创建动态内存

2.3.1函数原型

void_ realloc(void_* ptr, size_t size);

  • ptr:要调整的内存地址
  • size:调整后的大小

2.3.2函数功能

  • 扩大或者缩小动态内存的大小

2.3.3注意事项

  • realloc函数开辟空间可能会改变原地址的位置
  • 开辟失败返回NULL,
  • 开辟成功两种:
    • 原地址有足够的空间:返回地址为原地址
    • 原地址没有足够的空间:返回地址不是原地址,

2.3.4realloc与malloc的关系

  • 当realloc的参数ptr为NULL时,与malloc的功能相同

2.4free释放动态内存

2.4.1函数原型

void free(void* ptr);

2.4.2函数功能

  • 释放动态内存

2.4.3注意事项

  • 如果参数为NULL,则free什么都不做
  • 如果ptr指向的空间是在栈区,则行为未定义

3.使用动态内存的常见错误

3.1对NULL指针解引用

int main(void)
{
    int *ptr = (int*)malloc(40);
	*ptr = a;                        //此时malloc有可能创建失败,返回NULL,不可解引用

    free(ptr);
    ptr = NULL;
    return 0;
}
//正确版本
int main(void)
{
    int *ptr = (int*)malloc(40);
    if (p == NULL)                 //p=NULL时,不执行解引用操作
    {
        return 0;
    }
    else
		*ptr = a;                       

    free(ptr);
    ptr = NULL;
    return 0;
}

3.2对动态内存的越界访问

int main(void)
{
    int* p = (int*)malloc(20);
    if (p = NULL)
        return 0;

    int i = 0;
    for (i=0; i<10; i++)
    {
        *p = i+1;           //开辟20个字节,访问了40个字节,越界访问
    }
    free(p);
    p = NULL;
    return 0;
}

3.3多次释放动态空间

int main(void)
{
    int* p = (int*)malloc(20);
    if (p = NULL)
        return 0;
    free(p);
    free(p);           //    ----连续两次释放错误
    return 0;
}
//-----------解决办法

int main(void)
{
    int* p = (int*)malloc(20);
    if (p = NULL)
        return 0;
    free(p);
    p = NULL;       //由于参数未NULL时,free什么都不做,所以释放后应该加p=NULL,防止重复释放
    free(p);
    return 0;
}

3.4释放非动态内存

int main(void)
{
    int a = 0;

    free(&a);    //错误,不可释放非动态内存
    return 0;
}

3.5内存泄漏

int main(void)
{
    int* p = (int*)malloc(20);
    if (p = NULL)
        return 0;
                                         //不释放,会导致内存泄漏                                                                   	
    return 0;
}

3.6释放部分动态内存

int main(void)
{
    int* p = (int*)malloc(20);
	if (p = NULL)
        return 0;
    int i = 0;
    for (i=0; i<5; i++)
    {
        *p = i;
        p++;                 //由于此时p已经改变,故只free一部分空间
    }
    free(p);
    p = NULL;
    return 0;
}
//改正
int main(void)
{
    int* p = (int*)malloc(20);
	if (p = NULL)
        return 0;
    int i = 0;
    int* ptr = p;        //保存动态空间的起始地址
    for (i=0; i<5; i++)
    {
        *p = i;
        p++;                
    }
    free(ptr);
    ptr = NULL;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值