动态内存管理

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
//int main()
//{
//    //int a = 10;
//    //int arr[10] = {0};
//    //以上开辟好了不能再乱动
//    //malloc ——开辟内存空间,返回开辟空间的起始位置,若开辟失败,返回空指针
//    // void*malloc (size_t size)
//    //calloc ——返回开辟好空间的起始地址,再返回之前会将这片空间初始化为全零
//    // void*calloc(size_t num,size_t size) 开辟几个元素,以及每个元素的大小
//    //realloc
//    //free
//    //以上为动态内存管理的常用函数
//    int arr[10] = { 0 };//申请的空间在栈区(局部变量,形式参数)
//    int *p = (int*)malloc(40);//申请的空间在堆区(malloc,calloc,realloc,free)
//    if (p == NULL)
//    {
//        printf("%s", strerror(errno));
//        return 1;
//    }
//    //使用
//    int i = 0;
//    for (i = 0;i < 10;i++)
//    {
//        *(p + i) = i;
//        printf("%d ", *(p + i));
//    }
//    //没有free,不意味着内存空间就不回收了,
//    //当程序退出时,系统会自动回收空间
//    //内存泄露,不用又不还
//
//    free(p);//把p指向的空间释放掉
//    //空间允许给系统使用,但内部内容不清楚
//
//    //不过操作系统不会允许无节制的申请空间
//    p = NULL;
//    //这样就可以防止p是野指针
//    //NULL是系统找不到的空间
//
//
//
//    
//    return 0;
//}


//int main()
//{
//    int* p = (int*)calloc(10, sizeof(int));
//    if (p == NULL)
//    {
//        printf("%s\n", strerror(errno));
//        return 1;
//    }
//    int i = 0;
//    for (i = 0;i < 10;i++)
//    {
//        printf("%d ", *(p + i));
//    }
//    free(p);
//    p = NULL;
//    return 0;
//}

//想初始化,就用calloc,否则用malloc
//calloc = malloc + memset(起始位置,设定数据,类型大小)


//realloc
// void*realloc (void* ptr,size_t size)
//  指向要调整的空间的起始位置   追加后的大小
//
//int main()
//{
//    int *p = (int*)malloc(40);
//    if (p = NULL)
//    {
//        printf("%d", strerror(errno));
//        return 1;
//    }
//    int i = 0;
//    for (i = 0;i < 10; i++)
//    {
//        *(p + i) = i + 1;
//    }
//    //扩容
//    int * ptr = (int*)realloc(p, 80);
//    if (ptr != NULL)
//    {
//        p = ptr;
//    }
//    for (i = 0;i < 19;i++)
//    {
//        printf("%d ", *(p + i));
//    }
//    free(p);
//    p = NULL;
//    //不能直接用p接收,因为有可能扩容失败,导致p成为空指针
//    //
//    //情况一
//    // 直接追加就行,空间足够
//    // 情况二
//    // 直接追加不够,realloc在堆上找连续的并且是空的80个字节的空间,然后把旧的空间里的内容拷贝过来
//    //最后返回新的起始地址,并把旧的空间释放掉
//    //若malloc过多,会导致内存碎片化,导致内存使用效率下降
//    return 0;
//}

//常见的动态内存错误


//对NULL指针的解引用操作
//int main()
//{
//    int *p = (int*)malloc(40);
//    if (p == NULL)
//    {
//        printf("%s", strerror(errno));
//        return 1;
//    }//加上以上代码,对malloc、realloc、calloc检查
//    *p = 20;
//    free(p);
//    p = NULL;
//    return 0;
//}


//对动态开辟空间的越界访问
//int main()
//{
//    int* p = (int*)malloc(40);
//    if (p = NULL)
//    {
//        printf("%s", strerror(errno));
//        return 1;
//    }
//    //方式
//    int i = 0;
//    for (i = 0;i <= 10;i++)
//    {
//        p[i] = i;
//        //循环了11次,形成了越界访问
//    }
//    free(p);
//    p = NULL;
//    return 0;
//}


//对非动态开辟的空间进行释放
//int main()
//{
//    int a = 10;
//    int* p = &a;
//    free(p);
//    p = NULL;
//    //p不是动态开辟的,p在这里指向栈区的某个位置,free作用的是堆区
//    return 0;
//}


//使用free释放部分动态开辟的空间
//int main()
//{
//    int*p= (int*)malloc(40);
//    if (p == NULL)
//    {
//        return 1l;
//    }
//    int i = 0;
//    for (i = 0;i < 10;i++)
//    {
//        *p= i;
//        p++;
//        //若想不变,可写成
//        // p[i] = i;
//        //这样是p不变
//    }
//    free(p);
//    p = NULL;
//    //这里就是不完全的释放,p已经不指向起始位置
//    return 0;
//}


//对同一块空间多次释放
//int main()
//{
//    int* p = (int*)malloc(40);
//    free(p);//p的空间已经还给操作系统
//    free(p);//p仍指向还过的空间
//    //free后立刻将p置为空指针
//
//    return 0;
//}


//动态开辟内存忘记释放,导致内存泄漏
//void test()
//{
//    int* p = malloc(40);
//    int flag = 0;
//    scanf("%d", &flag);
//    if (flag == 5)
//    {
//        return;
//    }
//    free(p);
//    p = NULL;
//}
//int main()
//{
//
//    return 0;
//}

//经典的笔试题解析
// 对形参的修改不影响实参
// 对指针进行传参修改,需要取指针的地址,用二级指针接受
// strcpy不能往空指针里拷贝,NULL解引用会崩溃
// printf 直接打印字符串,字符串一般使用的是首字母地址,
// printf可以直接接收首字母地址,往后一直打印到\0
// 
// 函数一但return,就会把已经开辟的空间还给操作系统,这片空间不再属于当前程序,所以会让返回的指针变为野指针
// 不能返回局部变量的地址,原因就是上面
// 
// 返回栈空间地址的问题,使用完栈后会进行清除
//

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值