C语言内存知识

本文介绍了C语言中内存的五个区域:栈区、堆区、全局区、文字常量区和程序代码区,强调了堆栈的区别以及动态内存管理的重要性。讲解了malloc()和new在分配内存时的不同,以及释放内存的注意事项,包括delete和free操作后应将指针置空以防止悬挂指针。同时,对比了malloc/free和new/delete在处理对象时的区别。
摘要由CSDN通过智能技术生成

         

一直都把堆栈放一起,所以很多人会误以为他们的组合是一个词语,就像“衣服”一样简单,其实不然,今天在下就将最近学习总结的一些与大家分享。 
     一个由C/C++编译的程序占用的内存分为以下几个部分:
      1、栈区(stack):又编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构的栈。
      2、堆区(heap):一般是由程序员分配释放,若程序员不释放的话,程序结束时可能由OS回收,值得注意的是他与数据结构的堆是两回事,分配方式倒是类似于数据结构的链表。
     3、全局区(static):全局变量和静态变量被分配到同一块内存中,C语言中区分初始化和未初始化的,C++中不再区分了。
    4、文字常量区:常量字符串就是放在这里,程序结束后由系统释放。
    5、程序代码区:存放函数体的二进制代码。

*Data Segment中存放已初始化的全局或静态变量。

*BSS中存放未初始化的全局或静态变量。

 

malloc()动态开辟的从里获取空间。就是说malloc函数返回的指针是指向堆里的一块内存。操作系统中有一个记录空闲内存地址的链表,当操作系统收到程序的申请时,就会遍历链表。当使用 malloc() 分配过大的空间,比如超出 0x20ff8 这个常数(在我的系统(Fedora15)上是这样,别的系统可能会有变)时,malloc 不再从堆中分配空间,而是使用 mmap() 这个系统调用从映射区寻找可用的内存空间。如果你在函数上面定义了一个指针变量,然后在这个函数里申请了一块动态分配的内存让指针指向它。实际上,这个指针的地址是在栈上,但是它所指向的内容却是在堆上面。这一点要注意!所以,在一个函数里申请了空间后,比如:

void Function(void)   { char *p = (char *)malloc(100 * sizeof(char)); }

不要认为上面的函数返回,函数所在的栈被销毁指针也跟着销毁,申请的内存也就一样跟着销毁了。这是错误的。因为申请的内存在堆上,除非程序员手动释放,否则要等到程序结束释放所有内存才会释放它们,跟函数是否结束没有关系。也就是函数所在的栈被销毁跟堆完全没有关系。所以,忠告就是:使用完不再需要记得释放动态分配的内存!在该部分程序退出之前释放内存并立即给P赋0值(NULL)。另一个办法是保证P在没有初始化之前,将不再被使用。在函数中的new也是同样的,函数结束后并不会自动释放。
 

C++中

new
new运算返回所分配内存单元的起始地址,所以需要把返回值保存在一个指针变量中。若分配不成功,返回NULL,并抛出异常。
new没有为创建的对象命名,只能通过指针去访问对象或者数组。

delete
delete <指针变量>
delete []<动态分配的数组名>

new和delete必须配对使用。
虽然程序结束后系统会自动释放程序和其中数据所占的内存空间,但是为了在程序运行过程中能够重复使用有限的内存资源,防止系统产生内存泄漏,还是应该即时释放不需要的动态分配的内存单元,以便系统能随时对该内存单元进行分配。
delete释放内存,只是销毁内存上的对象,但是指针仍然存在,仍然指向原来的内存,保存原来空间的地址。所以我们应该在释放之后将指针置空,以避免后面不小心解引用造成问题。

malloc 和 new的区别?

malloc/free是标准库函数,new/delete是C++运算符
malloc失败返回空,new失败抛异常
new/delete会调用构造、析构函数,malloc/free不会,所以他们无法满足动态对象的要求。
new返回有类型的指针,malloc返回无类型的指针                                                                                                                          (很多编译器的new/delete都是以malloc/free为基础来实现的)

堆是操作系统维护的一块内存,而自由存储是C++中通过new与delete动态分配和释放对象的抽象概念。堆与自由存储区并不等价。自由存储区是两个动态内存区域之一,由new / delete分配/释放。对象生存期可以小于分配存储的时间;也就是说,自由存储对象可以在不立即初始化的情况下分配内存,并且可以在不立即释放内存的情况下将其销毁。在分配存储空间但在对象生命周期之外的时间段内,可以通过void *访问和操作存储空间,但不能访问原型对象的非静态成员或成员函数,也不能获取其地址,也不能对其进行其他操作。

堆是另一个动态内存区域,由malloc / free及其变体分配/释放。请注意,尽管默认的全局new和delete可能由malloc和特定编译器的free实现,但是堆与自由存储不同,并且在一个区域中分配的内存不能安全地在另一区域中释放。通过重新构造和显式销毁,可以将从堆分配的内存用于类类型的对象。如果这样使用,则有关自由存储对象生存期的注释在这里也类似适用。

 

特征new/deletemalloc/free
分配内存的位置自由存储区
返回类型安全性完整类型指针void*
内存分配失败返回值默认抛出异常返回NULL
分配内存的大小由编译器根据类型计算得出必须显式指定字节数
处理数组有处理数组的new版本new[]需要用户计算数组的大小后进行内存分配
已分配内存的扩充无法直观地处理使用realloc简单完成
是否相互调用可以,看具体的operator new/delete实现不可调用new
分配内存时内存不足无法通过用户代码进行处理能够使用realloc函数或重新制定分配器
函数重载允许不允许
构造函数与析构函数调用不调用

 

c语言----与const常量有关的内存分配https://blog.csdn.net/silently_frog/article/details/96737764

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值