IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言动态内存分配 -> 正文阅读

[C++知识库]C语言动态内存分配

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

???????? 在C语言中,我们开辟空间有静态开辟和动态开辟,静态开辟很简单,即直接开辟对应空间大小,多不退少不补,就像下面这种方式:

int a=10;//在栈区开辟4个字节
int char[10]={0};//在栈区开辟40个字节

这种方法很简单,但随着要解决的问题逐渐复杂,很多时候我们都是在程序运行的时候才知道需要多大的空间,这个时候就需要动态内存开辟了。

? ? ? ? 二.动态内存函数的介绍

????????1.内存被分为三个区域,动态内存开辟的空间是在放在堆区的,下图就是内存各区的使用情况。

栈区? 局部变量,形参

堆区

动态内存开辟

静态区

全局变量

静态变量

首先介绍malloc()函数,和free()函数,通过对该函数查询可知道

void* malloc (size_t size);
void free (void* ptr);
malloc()函数的返回类型是void*,参数是开辟空间的大小,单位是字节,开辟的是一块连续的空间;free()函数的返回类型是viod,参数是void*类型的指针。
#include<stdlib.h>//使用malloc()需要调用的头文件
#include<stdio.h>
int main()
{

    int* p = (int*)malloc(10 * sizeof(int));
    int i = 0;
    for (i = 0; i < 10; i++)

    {
        *(p + i) = i;
    }
    for (i = 0; i < 10; i++)
    {
        printf("%d ", p[i]);
    }

    free(p);//回收空间
    p = NULL;//及时置空
    return 0;
}

解释:因为 返回类型是void*,所以在使用的时候需要自己决定开辟的类型,这里开辟的是整型,所以用(int *)强制类型转换,并且申请了10个int大小,如果size是0,这是malloc()未定义的,取决于编译器;开辟成功后,malloc()会返回一个指向开辟空间的指针,这里用指针p接收,如果开辟失败会返回一个NULL,所以需要对malloc()的返回值好好检查。

free()函数,回收开辟的空间,和malloc()一起出现,如果free()的参数不是开辟的空间,该行为是未定义的,如果参数是NULL,那么什么都不做。

????????2.calloc()函数

????????

void* calloc (size_t num, size_t size);

? ? ? calloc()和malloc()使用方法差不多,但是参数不同,且calloc会初始化开辟的空间为0,malloc不会初始化。

int* p = (int*)calloc(10 , sizeof(int));
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        printf("%d ", p[i]);
    }

    free(p);
    p = NULL;

运行这一段代码会发现打印的全部是10个0。

????????3.realloc()函数

? realloc()即重新开辟空间,是基于malloc()和calloc()来使用的,

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

ptr是之前开辟空间的首地址,size_t是需要新的空间大小,具体使用如下:

int *p=(int*)malloc(10*sizeof(int));//假设开辟空间不够,还需要5个int大小的空间

realloc(p,15*sizeof(int));

int *str=realloc(p,15*sizeof(int));//检查realloc是否开辟成功,不能直接用p接收

if(str!=NULL)
{
    p=str;
}

realloc()开辟空间的具体情况如下,这样就好解释为什么要先用str来接收realloc返回值了。

?如果是第二种情况,realloc()会把之前的老空间的数据拷贝到新空间,然后主动释放老空间。其次,realloc()也可以实现和malloc()相似的功能,只要把指针设置成NULL。

????????三.动态内存常见错误

1.对NULL的解引用操作

int *p=(int *)malloc(INT_MAX*sizeof(int))//INT_MAX是整型最大值,这里太大了,开辟会失败
int i=0;
for(i=0;i<10;i++)
{
    *(p+i)=i;//对NULL解引用会出错
}

预防措施:开辟空间要合理;检查函数返回值是否为NULL。

2.对开辟空间的越界访问

int *p=(int *)malloc(40)//只开辟了40个字节
int i=0;
for(i=0;i<20;i++)
{
    *(p+i)=i;//开辟的空间不够存放20个整型
}

预防措施:空间开辟够,或者及时reallo()

3.对非开辟空间free操作

int a[10]={0};
int *p=a;
......  //一系列操作
free(p);
p=NULL;

4.free()开辟空间的一部分

int *p=(int *)malloc(40)//
int i=0;
for(i=0;i<5;i++)
{
    *p=i;//想对前5个元素初始化
    p++;//p已经不指向原来的起始位置
}
free(p);
p=NULL;

这种行为的风险是很大的,会造成内存泄漏,因为之前开辟的那个空间不知道在哪里了

5.对开辟空间多次释放

int *p=(int *)malloc(40)
......
free(p);
......
free(p);
p=NULL;

预防措施:释放空间后及时置空。

6.忘记释放开辟的空间

void test()
{ 
  int *p=(int*)malloc(40);
  if(p==NULL)
  {
    return ;
  }            //出了这个函数,就不能找到p,虽然出了函数p会销毁,但是malloc的空间不会释放
}          

int main
{
    test();   //这里不能free()test里面开辟空间的
    return 0;
}

这种情况也会造成内存泄漏,所以开辟的空间在不用后一定要及时释放。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-30 00:33:07  更:2022-09-30 00:35:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 5:21:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码