C进阶-动态内存管理

news2024/11/20 9:28:13

本章重点:

为什么存在动态内存分配?

动态内存函数的介绍  malloc  free  calloc  realloc

常见的动态内存错误

经典的笔试题

柔性数组

1.为什么存在动态内存分配

开辟空间的方式有两个特点:

1.    空间开辟大小是固定的。

2.    数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。

但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道,那数组的编译时开辟空间的方式就不能满足了。 这时候就只能试试动态存开辟了。

2.动态内存函数的介绍

动态内存管理函数: malloc、free、realloc、calloc

2.1malloc函数:

void* malloc (size_t size);

这个函数向内存申请一块连续可用的空间,并返回指向这块空间的指针。

如果开辟成功,则返回一个指向开辟好空间的指针。
如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
返回值的类型是 void* ,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。如果参数 size 为0,malloc的行为是标准是未定义的,取决于编译器。

 

free函数: 

void free (void* ptr);

free函数用来释放动态开辟的内存

如果参数 ptr 指向的空间不是动态开辟的,那free函数的行为是未定义的。如果参数 ptr 是NULL指针,则函数什么事都不做。

int main()
{
    //int arr[10];
    int* p = (int*)malloc(40);  // 使用malloc需要 #include <stdlib.h>

    if (p == NULL)
    {
        perror("malloc");
        return 1;
    }
    //开辟空间成功
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d\n",*(p+i));
    }

    free(p);   // 把p所指的空间释放
    p = NULL;

    return 0;
}

 2.2 callo函数

void* calloc (size_t num, size_t size);

函数的功能是为 num 个大小为 size 的元素开辟一块空间,并且把空间的每个字节初始化为0。
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0。 举个例子:

 

int main()
{
    //int* p  = (int*)calloc(INT64_MAX,sizeof(int)); //开辟失败
    int* p  = (int*)calloc(10,sizeof(int)); //开辟失败
    if (p == NULL)
    {
        perror("calloc");
        return 1;
    }

    //打印数据
    int i = 0;
    for (i = 0; i<10; i++)
    {
        printf("%d ",p[i]);
    }
    //释放
    free(p);
    p = NULL;

    return 0;
}

2.3 realloc

realloc函数的出现让动态内存管理更加灵活。
有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时候内存,我们一定会对内存的大小做灵活的调整。那 realloc 函数就可以做到对动态开辟内存大小的调整。 函数原型如下:

void* realloc (void* ptr, size_t size);

ptr 是要调整的内存地址

size 调整之后新大小
返回值为调整之后的内存起始位置。

这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到 新 的空间。 realloc在调整内存空间的是存在两种情况:

 

 

int main()
{
    int* p = (int*)malloc(40);
    if (p == NULL)
    {
        perror("malloc");
        return 1;
    }

    //初始化为1-10
    int i = 0;
    for (i = 0;i < 10;i++)
    {
        p[i] = i+1;
    }
    //增加一些空间
    int* ptr =  (int*)realloc(p,80);
    if (ptr != NULL)
    {
        p = ptr;
    }
    else
    {
        perror("realloc");
        return 1;
    }

    //打印数据
    for (i = 0; i< 20; i++)
    {
        printf("%d\n",p[i]);
    }
    //释放
    free(p);
    p = NULL;

    return 0;
}

3 常见的动态内存操作

3.1 对NULL指针的解引用操作

void test()
{
    int *p = (int *)malloc(INT_MAX/4);
    *p = 20;//如果p的值是NULL,就会有问题
    free(p);
}

int main()
{
    test();


    return 0;
}

3.2 对动态开辟空间的越界访问

int main()
{
    int i = 0;
    int *p = (int*)malloc(40);
    if(p == NULL)
    {
        perror("malloc");
        return 1;
    }
    for (i = 0; i < 20; i++)
    {
        p[i] = i;  //越界访问
    }
    free(p);
    p = NULL;

    return 0;
}

3.3 对非动态开辟内存使用free释放

int main()
{
    int a = 10;
    int* p = &a;
    printf("%d\n",*p);

    free(p);
    p = NULL;


    return 0;
}

3.4 使用free释放一块动态开辟内存的一部分

int main()
{
    int i = 0;
    int *p = (int*)malloc(40);
    if(p == NULL)
    {
        perror("malloc");
        return 1;
    }
    for (i = 0; i < 5; i++)
    {
        *p = i;
        p++;
    }

    //释放
    free(p);
    p = NULL;


    return 0;
}

3.5 对同一块动态内存多次释放

int main()
{
    int* p = (int*)malloc(40);
    if (p == NULL)
    {
        return 1;
    }
    //使用
    free(p);
    //p = NULL;

    free(p);
    return 0;
}

3.6 动态开辟内存忘记释放(内存泄漏)

void test()
{
    int *p = (int *)malloc(100);
    if(NULL != p)
    {
        *p = 20;
    }
}

int main()
{
    test();
    while(1);

    return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1094775.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Codeforces Round 846 (Div. 2) E. Josuke and Complete Graph 详解 数论分块

题目大意 题意来源 解题思路 首先我们假设存在 x x x满足 a , b ∈ [ l , r ] , g c d ( a , b ) x a,b\in[l,r],gcd(a,b)x a,b∈[l,r],gcd(a,b)x那么肯定 g c d ( ⌊ a / x ⌋ , ⌊ b / x ⌋ ) 1 就是互质 gcd(\lfloor a/x \rfloor, \lfloor b/x \rfloor)1就是互质 gcd(⌊a…

Js高级技巧—拖放

拖放基本功能实现 拖放是一种非常流行的用户界面模式。它的概念很简单&#xff1a;点击某个对象&#xff0c;并按住鼠标按钮不放&#xff0c;将 鼠标移动到另一个区域&#xff0c;然后释放鼠标按钮将对象“放”在这里。拖放功能也流行到了 Web 上&#xff0c;成为 了一些更传统…

如何制作电子画册更吸引读者?

电子画册是我们生活中最常见的书刊&#xff0c;无论是小公司还是大企业&#xff0c;都会制作一本属于自己的电子画册&#xff0c;可如何制作更加吸引读者的电子画册&#xff1f;这可难倒了好多人。 其实&#xff0c;制作一份好的电子画册需要一定的技巧和经验&#xff0c;比如…

【爬虫实战】python微博热搜榜Top50

一.最终效果 二.项目代码 2.1 新建项目 本文使用scrapy分布式、多线程爬虫框架编写的高性能爬虫&#xff0c;因此新建、运行scrapy项目3步骤&#xff1a; 1.新建项目: scrapy startproject weibo_hot 2.新建 spider: scrapy genspider hot_search "weibo.com" 3…

AI低代码维格云日历视图怎么用?

日历视图,是一个以天为单位,清晰展示当月所有日程的视图。在团队协作的过程中,我们常常会碰到以下场景: 制作项目日历,让团队成员知道每天需要完成什么任务; 制作排课表,给老师和教室安排课程; 制作会议日历,提醒团队成员进行每周计划与回顾; 制作营销日历,把握全年…

23面向对象案例1

目录 1、计算连续表达式的一个过程 2、优化后的代码 为什么不能return resultn&#xff1f; 3、用面向对象的方法可以解决冗余的问题&#xff0c;但是还是不能解决result的值可以被随意修改的问题 4、解决不能被随意修改的问题&#xff0c;可以将类属性改成私有变量吗&…

Marvin攻击25 年之久的RSA解密漏洞重现

1998 年发现的与 SSL 服务器中的 PKCS #1 v1.5 填充相关的缺陷&#xff08;据信已得到解决&#xff09;至今仍然影响着多个广泛使用的项目。 经过衡量端到端操作的广泛测试后&#xff0c;红帽研究人员发现了原始定时攻击的几种变体&#xff0c;统称为“马文攻击”&#xff0c;…

343. 整数拆分 96.不同的二叉搜索树

343. 整数拆分 设dp[i]表示拆分 数字i 出来的正整数相乘值最大的值 (i - j) * j,和dp[i - j] * j是获得dp[i]的两种乘法&#xff0c;在里面求最大值可以得到当前dp[i]的最大值&#xff0c;但是这一次的得出的最大值如果赋值给dp[i]&#xff0c;可能没有没赋值的dp[i]大&#…

springboot aop详解

springboot aop的实现方式有哪些 在 Spring Boot 中&#xff0c;AOP&#xff08;面向切面编程&#xff09;是通过 Spring Framework 提供的 AOP 模块来实现的。Spring AOP 提供了几种实现方式来应用切面编程&#xff0c;包括以下几种&#xff1a; 基于代理的 AOP&#xff1a; …

CSS变量 var()的用法

写在前面 这里介绍一下开发中常用的css变量var()&#xff0c;它可以实现样式的动态设置&#xff0c;使用方法主要分为全局使用和局部使用两种。 如何定义CSS变量var() 在CSS文件中&#xff0c;变量需要使用 – 作为前缀来定义&#xff0c;后面跟上变量名和值&#xff0c;如&a…

基于人工电场优化的BP神经网络(分类应用) - 附代码

基于人工电场优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于人工电场优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.人工电场优化BP神经网络3.1 BP神经网络参数设置3.2 人工电场算法应用 4.测试结果…

ARM +FPGA GPIB IP核实现

目前在数据发生其技术上居领先的是美国的 Tektronix 公司和 Agilent 公司。 Agilent 公司的台式脉冲 / 数据发生器家族的最高时钟频率达 3GHz &#xff08;定 时发生器&#xff09;&#xff0c;数据发生器 E81200 在通道数为 8CH 时数据速率为 660Mb/s, 即可以产…

22python生命周期的一种案例

第一个问题&#xff0c;什么叫生命周期&#xff1f; 生命周期就是一个对象从产生到消亡的一个周期过程&#xff0c;总体来说是一个这样的 展示一下生命周期的一点点的小案例吧~ 1、利用全局变量 #以下是一个python展示生命周期的方法过程 personCount 0 class Person:def _…

月薪过二万的Java面试

文章目录 &#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查设计师、个人社区创始人、开源项目贡献者。&#x1f30e;跑过十五…

创新YOLOv5改进:结合全新可变形大核注意力(D-LKA Attention)实现多尺度目标涨点

🔥🔥🔥 提升多尺度目标检测,创新提升 🔥🔥🔥 🔥🔥🔥 捕捉图像特征和处理复杂图像特征 🔥🔥🔥 👉👉👉: 本专栏包含大量的新设计的创新想法,包含详细的代码和说明,具备有效的创新组合,可以有效应用到改进创新当中 👉👉👉: 🐤🐤�…

Java并发面试题:(一)线程的5种状态及转换

线程的状态转换 1、新建状态&#xff08;New&#xff09;&#xff1a;新创建了一个线程对象。 2、就绪状态&#xff08;Runnable&#xff09;&#xff1a;线程对象创建后&#xff0c;其他线程调用了该对象的start()方法。该状态的线程位 于可运行线程池中&#xff0c;变得可运…

设计模式(1)-设计模式前置基础知识

1&#xff0c;设计模式概述 1.1 软件设计模式的产生背景 "设计模式"最初并不是出现在软件设计中&#xff0c;而是被用于建筑领域的设计中。 1977年美国著名建筑大师、加利福尼亚大学伯克利分校环境结构中心主任克里斯托夫亚历山大&#xff08;Christopher Alexand…

三大方法快速发现商业规律

文章目录 三大方法快速发现商业规律一、市场调研二、数据分析三、案例分析 &#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作者、产品软文创造者、技术文章评审老师、问卷调查…

新时代高效记账:自动化智能如何进行财务管理

随着科技的不断发展&#xff0c;自动化智能已经逐渐渗透到我们生活的各个领域。在财务管理中&#xff0c;自动化智能的应用显得尤为重要。它不仅可以提高财务管理的效率和精度&#xff0c;还能帮助我们更好地规划和掌控公司的财务状况 晨曦记账本提供了多种高效财务管理工具。…

【linux kernel】对linux内核设备的注册机制和查找机制分析

文章目录 1、简介2、device_initialize分析3、device_add分析4、总结 &#x1f53a;【linux内核系列文章】 &#x1f449;对一些文章内容进行了勘误&#xff0c;本系列文章长期不定时更新&#xff0c;希望能分享出优质的文章&#xff01; 1、《linux内核数据结构分析之哈希表》…