C与C艹的内存管理方式
C 内存开辟出的空间一般可以分成:代码段,数据段(初始化的数据段, 为初始化的数据段BSS),堆,栈

int i= 0x22222222;
char szTest [] = "aaaa";//a的ASCII码为0x61
func(i, szTest);
当访问进入func函数时,栈中的形式为(左侧地址 右侧数据):
0x0013FCF0 0x0013FCF8
0x0013FCF4 0x22222222
0x0013FCF8 0x61616161
PS: c++中语句解析顺序和函数调用时候顺序一致:由右向左!
比如如下语句,在输入vector为空时会造成 访问越界!
void numIslands(vector<vector<char>>& grid) {
const int n = grid.size(), m = grid[].size();
}
这里与if语句中的条件判断语句解析顺序相反(从左至右解析if语句).
c++内存开辟区域分为: 堆 栈 自由存储区 全局/静态存储区 常量存储区
自由存储区: 由malloc等分配的内存块,他和堆(new)类似,只不过用free结束自己的生命周期. (其实,可以看做是堆的剩余空间.)
堆: 由new分配的内存块,程序员手动控制生成和释放(delete).如果程序员没有是放掉,操作系统自动收回.
栈: 在执行函数时,函数内部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存内置于处理器的指令集中,效率很高,但是分配的内存容量有限 .
全局/静态存储区: 全局和静态变量被存储在这个区域. C中将这个区域分为 初始化的 和 为初始化的数据段.C++中二者公用这个区域
常量存储区: 存放 const常量 不允许修改.
****************************以上是基础准备****************************
malloc与new的区别:
c++中出现了new与delete这种动态分配内存的方法.
(1)malloc在自由存储区 而new在堆区.
(2)malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。
所以标准库函数与运算符可以做的事情是不一样的.
malloc与free是不在编译器控制权限之内,不能把构造函数和析构函数的任务强加于malloc/free.
Here,在biubiu的时候写cocos2d-x,前端就是c++的语法.在一个场景结束的时候总是崩溃,最后问题定位到析构函数.发现类在结束的时候并没有调用析构函数.导致类中使用的一些内存区域没有被释放掉(本来是要留到析构函数里面运行释放内存指针置空的)最后发现是在累的创建时没有使用new而是使用的malloc,然后手动初始化函数,但是析构时并没有手写销毁函数,而是直接将操作写到了析构函数中,但并没有被执行.
对于非内部数据类型,光用malloc/free无法满足动态对象的要求.因此,C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。
#include <iostream>
using namespace std; class Obj
{
public: Obj(void) { cout <<"Initialization"<<endl;} ~Obj(void) { cout<<"Destory"<<endl;} void initialization(){ cout<<"Initialization"<<endl;} void destory(){ cout<<"Destory"<<endl;}
}; void useMallocFree(void)
{
Obj *a = (Obj* ) malloc(sizeof(Obj));
//a->initialization();
//a->destory();
free(a);
} void useNewDelete(void)
{
Obj *a = new Obj();
delete a;
}
int main()
{
useMallocFree();
useNewDelete();
return ;
}
因为内部类型没有构造和析构函数,所以二者使等效的.既然new/delete可以覆盖malloc/free的功能为啥还要在C艹中保留malloc/free呢?为了在C艹中调用c程序,毕竟c只支持malloc.
如果 free new出来的空间,那么可能会因为没执行析构函数而出错;如果delete malloc出来的空间看似没问题,但是可读性很差.所以,建议 配对使用!.!
对于堆和栈:
(1)频繁的new/delete操作 势必会造成内存碎片化;而栈空间不存在内存碎片化问题.
(2)成功在函数中开辟内存的方法: a.主函数中给开辟函数传递 指针的地址,在函数中使用二级指针;
b.开辟函数返回开辟成功的内存首地址给主函数指针.
关于如何防止内存空间(堆)碎片化:
(1)对每一个类重载 new 和 delete. ;目的是从不同固定大小的内存池中分配不同的对象.全局重载或者单个类重载. 使用 malloc外面封装成new 参数是字节数. free 外面封装 delete
出现问题的情况:
(1)内存泄露:手动开辟内存空间后,如果没有释放该空间,而且指向该空间的指针指向了别的内存区域,那么造成该空间无法释放.
(2)野指针:释放内存后要把指向它的指针置为NULL,否则 if != NULL 语句就不能判断出是否是空内存.
指针与数组:
完全不一样! 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变.
指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存。指针远比数组灵活,但也更危险。
注意:
char *GetString(void){
char p[] = "hello world";
return p; // 编译器将提出警告
}
void Test4(void){
char *str = NULL;
str = GetString(); // str 的内容是垃圾
cout<< str << endl;
}
与
char *GetString2(void){
char *p = "hello world";
return p;
}
void Test5(void){
char *str = NULL;
str = GetString2();
cout<< str << endl;
}
的区别,前者输出错误,后者输出正确.字符数组开辟在栈上,函数结束自动释放. 字符常量开辟在全局静态存储区.是只读的内存快.
C与C艹的内存管理方式的更多相关文章
- glusterfs 内存管理方式
glusterfs中的内存管理方式: 首先来看看glusterfs的内存管理结构吧: struct mem_pool { struct list_head list; int hot_count; i ...
- 24小时学通Linux内核之内存管理方式
昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今天将会讲诉Linux如何追踪和管理用户空间进程的可用内 ...
- windows内存管理方式以及优缺点
Windows内存管理方式:页式管理,段式管理,段页式管理 页式管理 将各进程的虚拟空间(逻辑地址)划分为若干个长度相等的页,业内管理把内存空间(物理内存)按照页的大小划分为片或者页面,从而实现了离散 ...
- 十天学Linux内核之第三天---内存管理方式
原文:十天学Linux内核之第三天---内存管理方式 昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今 ...
- ObjC如何通过runtime修改Ivar的内存管理方式
ObjC如何通过runtime修改Ivar的内存管理方式 为什么要这么做? 在iOS 9之前,UITableView(或者更确切的说是 UIScrollView)有一个众所周知的问题: propert ...
- 这篇关于Oracle内存管理方式的介绍太棒了!我必须要转发,很全面。哈哈~
"Oracle内存管理可分为两大类,自动内存管理和手动内存管理.其中手动内存管理又可分为自动共享内存管理,手动共享内存管理,自动PGA内存管理以及手动PGA内存管理.本文会简单的介绍不同的内 ...
- (笔记)Linux内核学习(九)之内核内存管理方式
一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...
- Linux内核学习笔记——内核内存管理方式
一 页 内核把物理页作为内存管理的基本单位:内存管理单元(MMU)把虚拟地址转换为物理 地址,通常以页为单位进行处理.MMU以页大小为单位来管理系统中的也表. 32位系统:页大小4KB 64位系统:页 ...
- glibc内存管理方式
程序员接触的内存空间和系统接触的物理内存空间是有所区别的.对于一般进程来讲,他面对的是一个线性虚拟内存空间:地址从0到最大值.每一个进程面对的虚拟内存空间都是一样的,都享有全部的内存地址.虚拟内存空间 ...
随机推荐
- 3.6.5 空串与Null串
空串""是长度为0的字符串.可以调用以下代码检查一个字符串是否为空: String s = "greeting"; ...
- VM 与 与 Linux 的安装
[VMWare 安装] 输入后, [CentOS ] 1 检查 BIOS 虚拟化 2.新建虚拟机 3.新建虚拟机向导 4创建虚拟空盘 5 安装 Linux 系统对应的 CentOS 6 虚 ...
- java 项目连接MySQL数据库
1.导入jar包 mysql-connector-java-5.1.35百度云链接如下: 链接:https://pan.baidu.com/s/1DPvIwU_An4MA3mU5bQa6VA 密码:5 ...
- 小朋友的数字(codevs 3293)
题目描述 Description 有n个小朋友排成一列.每个小朋友手上都有一个数字,这个数字可正可负.规定每个小朋友的特征值等于排在他前面(包括他本人)的小朋友中连续若干个(最少有一个)小朋友手上的数 ...
- ECMAScript 6 入门学习笔记(零)——开始
所有es6笔记都是我自己提出来的一些点,没有很详细的例子什么的,这个链接就是我看的教程,有需要的可以看看.(http://es6.ruanyifeng.com/#docs/intro) 1.ECMAS ...
- NOIP2013 提高组合集
NOIP 2013 提高组 合集 D1 T1 转圈游戏 快速幂裸题 #include <iostream> #include <cstdio> #include <cst ...
- Oracle怎么用(常用工具)
Oracle数据库管理系统装好了!那要怎么用呢? 将介绍的工具:①Database Configuration Assistant ②SQL Plus ③SQL Developer 一.Dat ...
- Ubuntu安装deb时错误:“dpkg:错误:另外一个进程已经为 dpkg 状态数据库 加锁”解决
以下方式任选一个即可: 1.重启系统 2.执行(这种方式不要尝试,系统很容易挂) sudo rm /var/lib/dpkg/lock 然后执行修复 sudo dpkg --configure -a
- iOS 文字属性字典
iOS开发过程中相信大家常常遇到当须要给字体,颜色,下划线等属性的时候參数是一个NSDictionary 字典 可是字典里面究竟有哪些键值对了 我们把经常使用的总结一下 首先我们创建一个最简单的.设置 ...
- C#之快速排序
算法描述 1.假定数组首位元素为“枢轴”,设定数列首位(begin)与末位(end)索引: 2.由末位索引对应元素与“枢轴”进行比较,如果末位索引对应元素大于“枢轴”元素,对末位索引减一(end--) ...