关于C/C++内存管理示例详解

 更新时间:2021年05月08日 10:01:59   作者:程序员欢欢  
这篇文章主要给大家介绍了C/C++内存管理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1、内存分配方式

在C++中,内存分成五个区,分别是堆、栈、自由存储区、静态存储区和常量存储区。

1) 栈

执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置处理器指令集中,效率很高,但分配的内存容量有限。

2) 堆

由new分配的内存块,释放由程序员控制。如果程序员没有释放,那么就在程序结束的时候,被操作系统回收。

3) 自由存储区

由malloc等分配的内存块,用free结束自己的生命。

4) 静态存储区

全局变量和静态变量被分配到同一块内存中。C语言中,全局变量分为已初始化和未初始化。

5) 常量存储区

里面存放的是常量,不允许修改。 

2、堆和栈的区别

int * ptr = (int*)malloc(sizeof(int)*4);

在栈中存放了一个指向堆内存的指针ptr。在程序会先确定在堆中分配内存的大小,然后利用operator new分配内存,然后放回这块内存的首地址,放在栈中。

1) 空间大小不同

在32位系统中,堆的空间是4G,而栈的空间很小。

2) 分配方式不同

堆是动态分配的,没有静态分配。栈的静态分配时编译器完成的,动态分配由alloca函数分配。栈的动态分配由编译器进行释放。

3) 管理方式不同

栈是由编译器自动管理。堆的释放是由程序员控制。

4) 生长方式不同

堆的生长方式是向上的,向着内存地址增加的方向。栈的生长方式是向下的,是向着内存地址减小的方向。

5) 能否产生碎片

对于堆,频繁的new/delete会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。

6) 分配效率不同

栈是机器系统系统的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定栈的效率比较高。

堆是C/C++函数库提供的,库函数会按照一定的算法,在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。

3、operator new和operator delete

3.1 为什么要进行重载?

在嵌入式系统中,由于内存的限制,频繁的动态分配不定大小的内存会引起很大的问题以及堆破碎的风险。

当你必须要使用new和delete的时候,你不得不控制C++中的内存分配。你需要用重载的全局new和delete代替系统的内存分配符。需要给类重载new和delete。

一个防止内存破碎的方法是从不同固定大小的内存池中分配不同类型的对象。对单个类重载new和delete,你就可以灵活的控制内存分配。

3.2 重载全局的new和delete操作符

void* operator new(size_t size)
{
	void* p = malloc(size);
	return (p);
}

void operator delete(void*p)
{
	free(p);
}

3.3 类重载new和delete

为单个类重载new和delete

class TestClass
{
public:
	void* operator new(size_t size)
	{
		void* p = malloc(size);
		return p;
	}
	void operator delete(void* p)
	{
		free(p);
	}
};

为单个类重载new[] 和 delete[]

class TestClass
{
public:
	void* operator new[](size_t size)
	{
		void* p = malloc(size);
		return p;
	}
	void* operator delete[](void* p)
	{
		free(p);
	}
}

int main()
{
	TestClass* p  = new TestClass[10];
	delete [] p; 
	return 0;
}

注意:new[] 中的个数参数是数组的大小加上额外的存储对象数目的字节。考虑到内存分配机制的因素,尽量避免使用对象数组。

4、有了malloc/free为什么还要new/delete

malloc和free是C/C++语言的标准库函数,new / delete是C++ 的运算符。都用于申请动态内存和释放内存。

malloc / free 无法满足动态对象的要求。对象在创建的同时同时自动执行构造函数,对象消亡之前自动执行析构函数。即就是C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理和释放内存工作的运算符delete。

内部数据类型的对象没有析构和构造的过程,所以对于他们来说malloc / free和new / delete是等价的。

5、内存耗尽的三种解决方法

在申请动态内存时,找不到足够大的内存块,malloc和new将返回NULL指针。

1)判断指针是否为NULL,如果是则使用 return 终止函数

2)判断指针是否为NULL,如果是则使用 exit(1) 终止程序

3)为malloc和new 设置异常处理函数 。

总结

到此这篇关于C/C++内存管理的文章就介绍到这了,更多相关C/C++内存管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MFC创建右键弹出菜单的方法

    MFC创建右键弹出菜单的方法

    这篇文章主要介绍了MFC创建右键弹出菜单的方法,较为详细的分析了创建菜单资源及视类添加WM_RBUTTONDOWN消息的实现方法,是非常实用的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-01-01
  • C语言每日练习之求两个矩阵的乘积详解

    C语言每日练习之求两个矩阵的乘积详解

    这篇文章主要介绍了如何求两个矩阵的乘积,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-11-11
  • C++Vector容器常用函数接口详解

    C++Vector容器常用函数接口详解

    最近我学习了C++中的STL库中的vector容器,对于常用容器,我们不仅要会使用其常用的函数接口,我们还有明白这些接口在其底层是如何实现的。所以特意整理出来一篇博客供我们学习
    2022-08-08
  • C语言实现三角函数表

    C语言实现三角函数表

    这篇文章主要为大家详细介绍了C语言三角函数表,打印出相对应的三角函数值,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06
  • C++中char*转换为LPCWSTR的解决方案

    C++中char*转换为LPCWSTR的解决方案

    最近在学习C++,遇到了一个char*转换为LPCWSTR的问题,通过查找资料终于解决了,所以下面这篇文章主要介绍了C++中char*转LPCWSTR的解决方案,文中通过详细的示例代码介绍的很详细,有需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-01-01
  • Java C++ 题解leetcode1619删除某些元素后数组均值

    Java C++ 题解leetcode1619删除某些元素后数组均值

    这篇文章主要为大家介绍了Java C++ 题解leetcode1619删除某些元素后数组均值示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • QT实现简单计算器功能

    QT实现简单计算器功能

    这篇文章主要为大家详细介绍了QT实现简单计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • C语言实现求定积分的方法

    C语言实现求定积分的方法

    这篇文章主要介绍了C语言实现求定积分的方法,涉及C语言操作相关数学函数的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • C语言职工管理系统设计

    C语言职工管理系统设计

    这篇文章主要为大家分享了一份C语言职工管理系统设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • 带你了解C++中的sort函数

    带你了解C++中的sort函数

    这篇文章主要给大家介绍了关于C++中sort函数的基础入门使用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用C++具有一定的参考学习价值,需要的朋友们下面来一起看看吧
    2021-08-08

最新评论