C/C++内存管理
1. 静态内存
静态内存是指在程序开始运行时由编译器分配的内存,它的分配是在程序开始编译时完成的,不占用CPU资源。程序中的各种变量,在编译时系统已经为其分配了所需的内存空间,当该变量在作用域内使用完毕时,系统会自动释放所占用的内存空间。变量的分配与释放,都无须程序员自行考虑。
eg:基本类型,数组
2. 动态内存
用户无法确定空间大小,或者空间太大,栈上无法分配时,会采用动态内存分配。用malloc或者new申请任意多少的内存,程序员自己负责在何时用free或者delete手动释放内存。只用malloc或new分配的内存在堆里。
3.静态内存和动态内存的区别
(1) 静态内存分配在编译时完成,不占用CPU资源; 动态内存分配在运行时,分配与释放都占用CPU资源。
(2) 静态内存在栈(stack)上分配; 动态内存在堆(heap)上分配。
(3) 动态内存分配需要指针和引用类型支持,静态不需要。
(4) 静态内存分配是按计划分配,由编译器负责; 动态内存分配是按需分配,由程序员负责。
4.内存分配方式
虚拟内存结构:
注:这里谈的分配,都是指在虚拟内存中的分配。实际的分配需要做的是将虚拟地址映射到物理地址(段页式存储管理)。
内存分配方式一共有三种:
(1)从静态存储区域分配(全局变量,静态变量,在虚拟内存的数据段)
内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,例如,全局变量,静态变量。
(2)在栈上创建(局部变量,在虚拟内存的栈,属于静态内存)
在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束后这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)在堆上分配,亦称动态内存分配(malloc或者new申请,在虚拟内存的堆里,即在“空洞”里,属于动态内存)
程序在运行的时候用malloc或者new申请任意多少的内存,程序员自己负责在何时用free或者delete手动释放内存。动态内存的生存期由程序员决定,使用非常灵活,但是问题也多。
5.内存释放问题
(1)静态存储区域以及创建的栈,在函数执行完以后,出栈销毁,这个过程会自动释放静态分配的内存,不需要程序员手动操作;
(2)而动态分配的内存,实际是在堆上,系统没法自动释放堆上的内存,需要程序员手动写free或者delete函数来告诉系统需要释放堆上哪个位置的内存;
6.常见的内存错误及对策
(1)内存尚未分配成功,却使用了它;
解决办法:在使用内存之前检查指针是否为NULL。如果指针p是函数的参数,那么在函数的入口使用assert(p != NULL) 进行检查,如果是用malloc或者new来申请的,应该用if (p == NULL)或者 if (p != NULL) 来进行防错处理。
(2)内存分配虽然成功,但是尚未初始化就引用它;
错误原因:一是没有初始化的观念,二是误以为内存的缺省初值全为零,导致引用初值错误(如数组)。
解决办法:内存的缺省初值是什么并没有统一的标准,尽管有些时候为零值,但是宁可信其有,不可信其无,无论以何种方式创建数组,都要赋初值。
int *p1,*p2;
int a=100,b=60;
p1=&a;
p2=&b;
//或者*p1=a;*p2=b;
printf("%d,%d\n",*p1,*p2);//100,60
(3)内存分配成功并初始化,但是超过了内存的边界;
这种问题常出现在数组越界,写程序是要仔细。
(4)忘记释放内存,造成内存泄露;
含有这种错误的函数每次被调用都会丢失一块内存,开始时内存充足,看不到错误,但终有一次程序死掉,报告内存耗尽。
7.内存管理需要遵循的规则
(1)用malloc 或者 new 申请内存之后,应该立即检查指针值是否为 NULL ,防止使用指针值为NULL的内存;
(2)不要忘记数组和动态内存赋初值,防止未被初始化的内存作为右值使用;
(3)避免数组或者指针下标越界,特别要当心“多1”或者“少1”的操作;
(4)动态内存的申请与释放必须配对,防止内存泄露;
(5)用free或者delete释放了内存之后,立即将指针设置为NULL,防止产生“野指针”。
8.动态内存管理操作
8.1动态内存分配
//函数说明
#include<stdio.h>
void *malloc(size_t size);
void *calloc(size_t nmemb,size_t size);
(1)malloc的参数size表示分配的内存空间的大小,单位是字节Byte。
(2)calloc的参数nmemb表示分配的内存空间占的数据项数目,参数size表示一个数据项的大小,单位是字节Byte。也就是说calloc分配的是nmemb X size大小的内存空间。
两者的区别是calloc将初始化所分配的内存空间,把所有位设置为0。
(3)调用成功返回分配内存的地址,失败返回null。
8.2动态内存释放
//函数说明
#include<stdio.h>
void free(void *ptr);
动态内存示例:
#include<stdio.h>
#include<string.h>
char *upcase(char *inputstring);
int main(void)
{
char *str1;
str1=upcase("Hello");
printf("str1 = %s \n",str1);
free(str1);
return 0; }
//子函数中动态分配的内存的指针返回到主函数中
char *upcase(char *inputstring)
{
char *newstring;
int counter;
if(!(newstring=malloc(strlen(inputstring)+1))//为newstring分配动态内存,长度为strlen(inputstring)+1
{
printf("Error allocate memory!");
exit(255);
}
strcpy(newstring,inputsreing);
for(counter=0;counter<strlen(newstring);counter++)
{
if(newstring[counter]>=97 && newstring[counter]<=122)
{
newstring[counter]-=32;
}
}
return newstring;
}
C/C++内存管理的更多相关文章
- .NET基础拾遗(1)类型语法基础和内存管理基础
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...
- PHP扩展-生命周期和内存管理
1. PHP源码结构 PHP的内核子系统有两个,ZE(Zend Engine)和PHP Core.ZE负责将PHP脚本解析成机器码(也成为token符)后,在进程空间执行这些机器码:ZE还负责内存管理 ...
- linux2.6 内存管理——逻辑地址转换为线性地址(逻辑地址、线性地址、物理地址、虚拟地址)
Linux系统中的物理存储空间和虚拟存储空间的地址范围分别都是从0x00000000到0xFFFFFFFF,共4GB,但物理存储空间与虚拟存储空间布局完全不同.Linux运行在虚拟存储空间,并负责把系 ...
- linux2.6 内存管理——概述
在紧接着相当长的篇幅中,都是围绕着Linux如何管理内存进行阐述,在内核中分配内存并不是一件非常容易的事情,因为在此过程中必须遵从内核特定的状态约束.linux内存管理建立在基本的分页机制基础上,在l ...
- Objective-C内存管理之引用计数
初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...
- Quartz2D内存管理
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px "PingFang SC"; color: #239619 } p.p2 ...
- 浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...
- linux内存管理
一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分: 1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程 ...
- cocos2d-x内存管理
Cocos2d-x内存管理 老师让我给班上同学讲讲cocos2d-x的内存管理,时间也不多,于是看了看源码,写了个提纲和大概思想 一. 为什么需要内存管理 1. new和delete 2. 堆上申 ...
- Swift中的可选链与内存管理(干货系列)
干货之前:补充一下可选链(optional chain) class A { var p: B? } class B { var p: C? } class C { func cm() -> S ...
随机推荐
- 选择排序(SelectionSort)
http://blog.csdn.net/magicharvey/article/details/10274765 算法描述 选择排序是一种不稳定排序.选择排序每次交换一对元素,它们当中至少有一个将被 ...
- vmware漏洞之一——转:利用一个堆溢出漏洞实现VMware虚拟机逃逸
转:https://zhuanlan.zhihu.com/p/27733895?utm_source=tuicool&utm_medium=referral 小结: vmware通过Backd ...
- 1. Maven - 开始
今天开始记录Maven的学习过程. ☞ 相关明细 操作系统:win7 参考书籍:<maven-definitive-guide_zh>(Maven权威指南) maven版本:3.3.3 ☞ ...
- 【最大团转最大点独立集(匈牙利算法+时间戳优化)】BZOJ2744-[HEOI2012]朋友圈
[题目大意] 有两个国家A和B.存在以下朋友关系: 1.A国:每个人都有一个友善值,当两个A国人的友善值a.b,如果a xor b mod 2=1,那么这两个人都是朋友,否则不是: 2.B国:每个人都 ...
- 用Java Swing实现Freecell(空当接龙)
目录 引言 1 游戏规则 2 界面设计和大致逻辑 2.1 界面设计 2.2 大致逻辑 3 主要功能模块设计与实现 3.1 主要思路 3.2 主要工具类 3.3 异常类 3.4 游戏初始化模块 3.5 ...
- xml和集合混合使用-图书管理器
package com.book; public class Book { private int id; //图书编号 private String name; //图书名称 private Str ...
- Problem E: 矩阵鞍点
AC代码#include<stdio.h> int main() { ][]; ]; int i,j,t,n; while(scanf("%d",&n)!=EO ...
- Java高级架构师(一)第38节:Nginx的负载均衡模块
负载均衡: 1.热备:如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务.服务器处理请求的顺序:AAAAAA突然A挂啦,BBBBBBBBBBBBBB..... upstream ...
- ARM的存储器映射与存储器重映射
转:http://www.360doc.com/content/12/1006/00/1299815_239693009.shtml arm 处理器本身所产生的地址为虚拟地址,每一个arm芯片内都有存 ...
- mysql的存储目录
1.MySQL的数据存储目录为data,data目录通常在C:\Documents and Settings\All Users\Application Data\MySQL\MySQL Server ...
