一文读懂内存管理

news/2025/1/11 10:14:12/

1 野指针 野猫 野狗 野孩子 熊孩子 NULL地址-狗链子

野孩子:没人要,没人管的孩子;行为动作不守规矩,调皮捣蛋的孩子。    
野狗:没有主人的狗,没有链子锁着的狗,喜欢四处咬人。    
对付野孩子的最好办法是给他定一套规矩,好好管教。一旦发现没有按规矩办事就好.        
好收拾他。对付野狗最好的办法就是拿条狗链锁着它,不让它四处乱跑.       
对付也指针肯怕比对付野孩子或野狗更困难。   
我们需要把对付野孩子和野狗的办法都用上。既需要规矩,也需要链子。前面我们把内存比作尺子,很轻松的理解了内存。
尺子上的 0 毫米处就是内存的 0 地址处,也就是 NULL 地址处。
这条栓“野指针”的链子就是这个“NULL”。
定义指针变量的同时最好初始化为 NULL,用完指针之后也将指针变量的值设置为 NULL。
也就是说除了在使用时,别的时间都把指针“栓”到 0 地址处。
这样它就老实了。

2 栈、堆和静态区

一层教学楼,可能有外语教室,允许外语系学生和老师进入;
还可能有数学教师,允许数学系学生和老师进入;
还可能有校长办公室,允许校长进入。
同样,内存也是这样,内存的三个部分,不是所有的东西都能存进去的。静态区:保存自动全局变量和 static 变量(包括 static 全局和局部变量)。静态区的内容在总个程序的生命周期内都存在,由编译器在编译的时候分配。
栈:保存局部变量。 栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自动被销毁。其特点是效率高,但空间大小有限。
堆:由 malloc 系列函数或 new 操作符分配的内存。其生命周期由 free 或 delete 决定。在没有释放之前一直存在,直到程序结束。其特点是使用灵活,空间比较大,但容易出错。

3 常见内存错误

指针没有指向一块合法的内存

 定义了指针变量,但是没有为指针分配内存,即指针没有指向一块合法的内存。
1. 结构体成员指针未初始化
#include <cstring>
#include <stdlib.h>
#include <iostream>
struct student
{char *name;int score;
}stu,*pstu;int main()
{// 还没有为结构体分配内存//std::strcpy(stu.name,"Jimy");// 内存访问出错// stu.score = 99;struct student* pst = (struct student*)malloc(sizeof(struct student));pst->name = (char*)malloc(sizeof(char));// 这个好像不加上也可以,看编译器===std::strcpy(pst->name,"Jimy"); pst->score = 99;std::cout << pst->name << std::endl;free(pst);return 0;
}

函数 入口 的 指针变量检测 使用 assert(NULL != p)对参数进行校验

字符串拷贝 strlen(p1) 获取的长度 不包括结束符

char *p1 = “abcdefg”;
// char *p2 = (char *)malloc(sizeof(char)*strlen(p1));// 未包括结束符
char* p2 = (char*)malloc(sizeof(char)*(strlen(p1)+1));// 
// 不要因为 char 类型大小为 1 个 byte 就省略 sizof(char)这种写法。这样只会使你的代码可移植性下降.
strcpy(p2,p1);

memset 初始化内存

int a[10];
memset(a,0,sizeof(a));
// memset 函数有三个参数,
// 第一个是要被设置的内存起始地址;
// 第二个参数是要被设置的值;
// 第三个参数是要被设置的内存大小,单位为 byte。

内存越界

这种错误经常是由于操作数组或指针时出现“多 1”或“少 1”。比如:
int a[10] = {0};
for (i=0; i<=10; i++) // for (i=0; i<10; i++)  左闭右开写法=============
{a[i] = i;// 无 a[10]
}

内存泄漏 由malloc 系列函数或 new 操作符分配的内存。如果用完之后没有及时 free 或 delete,这块内存就无法释放,直到整个程序终止。

malloc 返回指针 NULL 申请0字节内存

申请 0 字节内存,函数并不返回 NULL,而是返回一个正常的内存地址。
但是你却无法使用这块大小为 0 的内存。
这好尺子上的某个刻度,刻度本身并没有长度,只有某两个刻度一起才能量出长度。
对于这一点一定要小心,因为这时候 if(NULL ! = p)语句校验将不起作用。

malloc 与 free 配对使用 一定要一夫一妻制,不然肯定出错。

malloc 两次只 free 一次会内存泄漏; malloc 一次 free 两次肯定会出错。
也就是说,在程序中 malloc 的使用次数一定要和 free 相等,否则必有错误。
这种错误主要发生在循环使用malloc 函数时,往往把 malloc 和 free 次数弄错了。

释放完块内存之后,没有把指针置 NULL,这个指针就成为了“野指针”,也有书叫“悬垂指针”。

这是很危险的,而且也是经常出错的地方。所以一定要记住一条: free 完之后,一定要给指针置 NULL。

参考
https://github.com/Ewenwan/ShiYanLou


http://www.ppmy.cn/news/6234.html

相关文章

Python 自动化测试(三): pytest 参数化测试用例构建

1080501 27.2 KB 在之前的文章中主要分享了 pytest 的实用特性&#xff0c;接下来讲 Pytest 参数化用例的构建。 如果待测试的输入与输出是一组数据&#xff0c;可以把测试数据组织起来用不同的测试数据调用相同的测试方法。参数化顾名思义就是把不同的参数&#xff0c;写到一个…

C++中delete 和 delete []的真正区别

1.我们通常从教科书上看到这样的说明&#xff1a; delete 释放new分配的单个对象指针指向的内存 delete[] 释放new分配的对象数组指针指向的内存 那么&#xff0c;按照教科书的理解&#xff0c;我们看下下面的代码&#xff1a; int *a new int[10]; delete a; //方…

LeetCode HOT 100 —— 581. 最短无序连续子数组

题目 给你一个整数数组 nums &#xff0c;你需要找出一个 连续子数组 &#xff0c;如果对这个子数组进行升序排序&#xff0c;那么整个数组都会变为升序排序。 请你找出符合题意的 最短 子数组&#xff0c;并输出它的长度。 思路 方法一&#xff1a;双指针 排序 最终目的是让…

Python求多元函数的极小值

文章目录minimize_scalarminimize测试minimize_scalar 此为scipy中用于求函数最小值的方法&#xff0c;输入参数如下 minimize_scalar(fun, bracketNone, boundsNone, args(), methodbrent, tolNone, optionsNone)[source]其中&#xff0c;必选的参数只有一个&#xff0c;就是…

【算法】P1 算法简介

算法什么是算法正确与错误的算法算法可以解决什么问题本专栏有哪些算法什么是算法 算法 (Algorithm) 取某个值或集合作为 输入&#xff0c;并产生某个值或集合作为 输出。算法就是把输入转换为输出的计算&#xff0c;描述这个计算的过程来实现输入与输出的关系。 正确与错误的…

业聚医疗在港交所上市:市值约76亿港元,钱永勋、刘桂祯夫妇控股

12月23日&#xff0c;业聚医疗集团控股有限公司&#xff08;下称“业聚医疗”&#xff0c;HK:06929&#xff09;在港交所上市。本次上市&#xff0c;业聚医疗的发行价为8.80港元/股&#xff0c;全球发行发售5463.30万股&#xff0c;募集资金总额约为4.81亿港元&#xff0c;募资…

12【SpringMVC的异常处理】

文章目录六、SpringMVC的异常处理6.1 SpringMVC异常概述6.2 SpringMVC异常处理6.2.1 单个类处理方式6.2.2 处理全局异常6.2.3 注解方式实现全局异常六、SpringMVC的异常处理 6.1 SpringMVC异常概述 我们在处理异常时&#xff0c;通常使用try…catch块来处理程序中发生的异常&…

Hadoop综合项目——二手房统计分析(MapReduce篇)

Hadoop综合项目——二手房统计分析&#xff08;MapReduce篇&#xff09; 文章目录Hadoop综合项目——二手房统计分析&#xff08;MapReduce篇&#xff09;0、 写在前面1、MapReduce统计分析1.1 统计四大一线城市房价的最值1.2 按照城市分区统计二手房数量1.3 根据二手房信息发布…