C语言中的内存分配与内存泄漏

引入

示例 1
        int nums[10] = {0}; //对
        int len = 10;
        int nums[len] = {0}; //错
        是因为系统的内存分配原则导致的

概述

        在程序运行时, 系统为了更好的管理进程中的内存 , 所以有了将内存进行了分配 , 其分配的机制
就称为内存分配

分配原则:

静态分配原则

特点 :
        1、在程序编译或运行过程中,按事先规定大小分配内存空间的分配方式。
        2、必须事先知道所需空间的大小。
        3、分配在栈区或全局变量区,一般以数组的形式。
        4、按计划分配。

动态分配原则

特点 :
        1、在程序运行过程中,根据需要大小自由分配所需空间。
        2、按需分配。
        3、分配在堆区,一般使用特定的函数进行分配。

注意:

c 语言中提供了一系列动态分配内存的函数 这些函数大部分都在stdlib.h 头文件中声明
        free 释放
        malloc 申请空间 , 默认值随机
        calloc 申请空间 , 默认值为 0
        realloc 扩展空间
        string.h中提供的函数
        memset 将 malloc 中的随机数设为 0

动态分配函数

memset函数

作用 : 重置
语法:
        #include <string.h>
        void *memset(void *s, int c, size_t n);
参数 :
        s:开始的位置
        c:重置后的数据
        n:重置的数量
        从s 开始 , n 个字节的数据 , 设置为 c
示例
#include<stdio.h>
#include<string.h>
int main(int argc, char const *argv[])
{
    char strs[10] = {0};
    memset(strs,'a',10*1);
    for (int i = 0; i < 10; i++)
    {
        printf("%c ",strs[i]);
    }
    printf("\n");
    int nums[10] = {1,2,3,4,5,6,7,8,9,10};
    memset(nums,0,10 * 4);
    for (int i = 0; i < 10; i++)
    {
        printf("%d ",nums[i]);
    }
    printf("\n");
    return 0;
}

free函数

作用 : 释放空间
语法:
        #include<stdlib.h>
        void free(void *ptr);
参数 :
        ptr:指针

malloc函数

作用 : 在堆内存中开辟空间
语法:
        void *malloc(size_t size)
参数 :
        size:开辟空间大小 , 单位字节 ,size_t 可以理解为无符号 int
返回值 :
        开辟的空间的地址
        开辟失败返回NULL
注意 :
        1,在使用 malloc 需要判断是否开辟成功
        2,如果多次 malloc 申请的内存,第 1 次和第 2 次申请的内存不一定是连续的
        3,malloc的返回值在使用中记得强制类型转换
        4,malloc从堆区申请空间后 空间的内容中的值是随机的 ( 与局部变量一样大概率 为0), 可以使用 memset 函数对空间中的数据进行置
示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    //1,申请空间
    //申请一个可以存储10个int数据的空间
    int *p = (int *)malloc(10 * sizeof(int));
    //2,判断是否开辟失败
    if (p == NULL)
    {
        printf("开辟失败\n");
        return 0;
    }
    //置0
    memset(p,0,10 *sizeof(int));
    //3,使用空间
    // for (int i = 0; i < 10; i++)
    // {
        // scanf("%d",&p[i]);
    // }
    for (int i = 0; i < 10; i++)
    {
        printf("%d ",p[i]);
    }
    printf("\n");
    //4,释放空间
    free(p);
    return 0;
}

calloc函数

作用 : 在堆内存中开辟空间
语法:
        void *calloc(size_t nmemb, size_t size);
参数 :
        nmemb:申请的块数
        size:每块的大小
返回值:
        开辟的空间的地址
        开辟失败返回NULL
        int *p = malloc(10 * sizeof(int));
        int *p = calloc(10,sizeof(int));
示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    //1,申请空间
    //申请一个可以存储10个int数据的空间
    // int *p = (int *)malloc(10 * sizeof(int));
    int *p = (int *) calloc(10,sizeof(int));
    //2,判断是否开辟失败
    if (p == NULL)
    {
        printf("开辟失败\n");
        return 0;
    }
    //置0
    //memset(p,0,10 *sizeof(int));
    //3,使用空间
    for (int i = 0; i < 10; i++)
    {
        scanf("%d",&p[i]);
    }
    for (int i = 0; i < 10; i++)
    {
        printf("%d ",p[i]);
    }
    printf("\n");
    //4,释放空间
    free(p);
    return 0;
}

realloc函数

作用 : 扩展空间
语法:
        void *realloc(void *ptr, size_t size);
参数 :
        ptr:原指针
        size:从新开辟的大小 , 原大小 + 新开的大小
返回值 :
        开辟成功返回新地址
        开辟失败返回NULL
注意 :
        新地址不一定等于原地址, 但是大概率相同

内存泄漏

概念

申请的内存,首地址丢了,找不了,再也没法使用了,也没法释放了,这块内存就被泄 露了。

情况1:记录申请的内存的指针变量指向别的地方

        int *p = (int *)malloc(40);
        int nums[10] = {};
        p = nums;

情况2:在函数中申请空间,使用完毕没有释放

        void test()
        {
                int *p = (int *)malloc(40);
        }
        test();

防止多次释放

示例
        int *p = (int *)malloc(40);
        free(p);
        free(p);
        //注意多次释放会报错
口诀 : 释放前判断 , 释放后置 NULL
    int *p = (int *)malloc(40);
    if(p != NULL)
    {
        free(p);
        p = NULL;
    }

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值