C和指针--动态内存分配
1.为什么需要使用动态内存分配
数组的元素存储于内存中连续的位置上,当一个数组被声明时,它所需要的内存在编译时就被分配。当你声明数组时,必须用一个编译时常量指定数组的长度。但是,数组的长度常常在运行时才知道,这是由于它所需的内存空间取决于输入数据。为了避免空间的浪费和超出范围的处理,需要使用动态内存分配。
2.常见的动态内存错误
- 动态内存分配最常见的错误就是忘记检查所请求的内存是否成功分配。被访问的内存可能保存了其他变量的值,对它进行修改将破坏那个变量,修改那个变量将破坏你存储在那里的值,这种类型的bug非常难以发现。
- 动态内存分配的第二大错误来源是操作内存时超出了分配内存的边界。在malloc和free的有些实现中,它们以链表的形式维护可用的内存池,对分配的内存之外的区域进行访问可能破坏这个链表,这有可能产生异常,从而终止程序。
当一个使用动态内存分配的程序失败时,人们很容易把问题的责任推给malloc和free函数。但是它们实际上很少是罪魁祸首。事实上,问题几乎总是出现在你自己的程序中,而且常常是由于访问了分配内存以外的区域引起的。
警告:
当你使用free时,可能出现各种不同的错误。传递给free的指针必须是一个从malloc、calloc或realloc函数返回的指针。传递给free函数一个指针,让它释放一块并非动态分配的内存可能导致程序立即或在晚些时候终止。试图释放一块动态分配内存的一部分也有可能引起类似的问题。
释放一块内存的一部分是不允许的。动态分配的内存必须整块一起释放。但是realloc函数可以缩小一块动态分配的内存,有效地释放它尾部的部分内存。
最后,必须小心,不要访问已经被free函数释放了的内存。假定你对一个指向动态分配的内存的指针进行了复制,而且这个指针的几份拷贝散布于程序各处。你无法保证当你使用其中一个指针时它所指向的内存是不是已经被另一个指针释放。另一方面,必须确保程序中所有使用这块内存的地方在这块内存被释放之前停止对它的使用。
3.内存泄漏
当动态分配的内存不再需要使用时,它应该被释放,这样它以后可以被重新分配使用。分配内存但在使用完毕后不释放将引起内存泄漏。在那些所有执行程序共享一个通用内存池的操作系统中,内存泄漏将一点点榨干可用内存,最终使其一无所有。要摆脱这种困境,只有重启系统。
其他操作系统能够记住每个程序当前拥有的内存段,这样当一个程序终止时,所有分配给它但未被释放的内存全部归还给内存池。但即使在之类系统中,内存泄漏仍然是一个严重的问题,因为一个持续分配却一点不释放内存的程序最终将耗尽可用的内存。
C和指针--动态内存分配的更多相关文章
- C++指针和动态内存分配
指针和动态内存分配 数组与指针 数组 数组名是一个指针常量. 数组名传递数据时,传递的是地址. 数组作为函数参数时不指定第一维大小. 对象数组 A a[2] = {A(1,2)}; 执行时先调用有参数 ...
- C和指针 第十一章 动态内存分配
声明数组时,必须指定数组长度,才可以编译,但是如果需要在运行时,指定数组的长度的话,那么就需要动态的分配内存. C函数库stdlib.h提供了两个函数,malloc和free,分别用于执行动态内存分配 ...
- 《C和指针》 读书笔记 -- 第11章 动态内存分配
1.C函数库提供了两个函数,malloc和free,分别用于执行动态内存分配和释放,这些函数维护一个可用内存池. void *malloc(size_t size);//返回指向分配的内存块起始位置的 ...
- C动态内存分配(C与指针实例)
主要初步介绍malloc.free.calloc.realloc的基本.日后会有更详细的内容. malloc.free分别用于动态内存分配和释放. malloc会从内存池里提取一块合适的内存(连续的) ...
- C++学习笔记(十一):void*指针、类型转换和动态内存分配
void*指针 void关键字表示“空类型”的概念.但是,这里的“空类型”不表示“任意类型”,而是表示不存在的意思,也就是说C/C++不允许你写语句void a,不存在类型为void的东西. void ...
- 数据结构基础——指针及动态内存分配(malloc)
一.指针 C语言中的指针是一种数据类型,比如说我们用int *a;就定义了一个指针a,它指向一个int类型的数.但是这个指针是未初始化的,所以,一般的,我们都在创建指针时初始化它,以免出错,在还不吃的 ...
- C和C指针小记(十六)-动态内存分配
动态内存分配 1.1 为什么使用动态内存分配 直接声明数组的方式的缺点: 1) 声明数组必须指定长度限制.无法处理超过声明长度的数组. 2) 如果声明更大的常量来弥补第一个缺点,会造成更多的内存浪费. ...
- c++ 动态数组,指针与动态内存分配
教学内容: 内存的使用 动态内存分配malloc函数 分配内存时使用sizeof运算符 用指针访问内存 以数组的形式访问内存 一.内存的使用 堆(heap) 在程序执行期间分配内存时,内存区域中的这个 ...
- <c和指针>学习笔记5动态内存分配和预处理器
1 动态内存 比如声明数组得时候,我们需要提前预估数组长度,分配大了浪费,少了就更不好操作了.从而引入动态分配,需要的时候再分配. (1)malloc和free void *malloc(size_t ...
随机推荐
- Unity 的 [HideInInspector]
[HideInInspector] public Transform t; public Transform mm; public Transform nn3; 在变量前面加入,作用:隐藏下一条在In ...
- jq append添加的元素click获取不到的解决方法
移动端手机ios网页,apppend添加html class名用 on()方法没效果 解决方案:在html里面给需要点击的元素加一个onclick="javascript:void(0)&q ...
- 《剑指offer》Q01-12 (牛客10.11)
目录 T1 二维部分有序数组查找 ☆ T2 字符串字符不等长替换 - 从后往前 T3 返回链表的反序 vector T4 重建二叉树 T5 两个栈模拟队列 T6 旋转数组中的最小元素 - 二分或暴力 ...
- AnroidStudio gradle版本和android插件的版本依赖
- 【VS开发】VC下加载JPG/GIF/PNG图片的两种方法
1.用API OleLoadPicture来加载JPG.GIF格式的图片(注:不支持PNG格式,另外GIF只能加载第一帧,且不支持透明) OleLoadPicture 函数实际上创建了一个IPictu ...
- 使用C++11原子量实现自旋锁
一.自旋锁 自旋锁是一种基础的同步原语,用于保障对共享数据的互斥访问.与互斥锁的相比,在获取锁失败的时候不会使得线程阻塞而是一直自旋尝试获取锁.当线程等待自旋锁的时候,CPU不能做其他事情,而是一直处 ...
- [LuoguP3064][USACO12DEC]伊斯坦布尔的帮派Gangs of Istanbull(加强版)_线段树_贪心
伊斯坦布尔的帮派Gangs of Istanbull 题目链接:https://www.luogu.org/problem/P3064 数据范围:略. 题解: 这个题其实分为两问,第一问是$YES$. ...
- 缓存穿透 & 缓存雪崩 & 缓存击穿
一 缓存穿透 1. 行为 查询一个一定不存在的数据.存储层(姑且认为是db,下面都用db指代)查不到数据则不写入缓存,那么下次请求这个不存在的数据同样会到db层查询,失去了缓存的意义.流量大或人为恶意 ...
- Ural 1298 Knight 题解
目录 Ural 1298 Knight 题解 题意 题解 程序 Ural 1298 Knight 题解 题意 给定一个\(n\times n(1\le n\le8)\)的国际象棋棋盘和一个骑士(基本上 ...
- ingress安装配置
Traefik Traefik 是一款开源的反向代理与负载均衡工具.它最大的优点是能够与常见的微服务系统直接整合,可以实现自动化动态配置.目前支持 Docker.Swarm.Mesos/Maratho ...