面试十三、malloc 、calloc、realloc以及new的区别

2024-04-22 07:44

本文主要是介绍面试十三、malloc 、calloc、realloc以及new的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

// 1 . 静态内存分配.bss 存储未初始化的全局变量和静态变量,在编译时被分配空间,但不会被初始化。在程序启动时,系统会将.bss段的数据初始化为零或者空值.data (静态数据区) : 存储已经初始化的全局变量和静态变量(静态局部和静态全局)的值栈:存储函数的局部变量和函数调用的参数堆:存储通常用于动态分配的内存.. image:: F:\C++\C++\STL\images\img.png// 2. 动态内存分配.. image:: F:\C++\C++\STL\images\img_1.png.. image:: F:\C++\C++\STL\images\img_2.png.. image:: F:\C++\C++\STL\images\img_3.pngmalloc/calloc/realloc/free区别:(1) malloc 函数:从堆上分配内存,内存不会被修改或者清空,返回首字节的地址,返回void*,失败返回nullptrint* str = (int *)malloc(sizeof(int));(2) calloc 函数: 从堆上分配内存并清零,malloc和realloc开辟空间后的数据为随机值函数原型   void *calloc(size_t nitems, size_t size)nitems -- 要被分配的元素个数。size -- 元素的大小。int *p calloc(5,sizeof(int))(3) realloc 函数:在之前分配的内存块的基础上,将内存重新分配为更大或者更小的部分第一个参数指向原内存块的指针,第二个是请求的大小。重新分配的块大小和第一个参数引用的块大小不同。返回值是指向重新分配的内存的指针函数原型:void *realloc(void *ptr , size_t size);a. 当第一个参数为nullptr时,功能等价于mallocb. 分两种情况:1. 原地址空间有连续的内存,则直接扩大,返回原地址的指针2. 原地址空间没有连续的内存,则重新开辟一片空间,将数据拷贝到新空间,释放原空间,返回新地址指针(注意显式释放问题,引起二次释放的问题)原地址的指针已经被释放了,小心第二次释放(4) 释放内存freevoid free(void *p)   ,释放之前有调用 calloc、malloc 或 realloc 所分配的内存空间,*p指针指向一个要释放内存的内存块。存在问题:1. 二次释放,如realloc新开辟空间,则会导致程序崩溃2. free释放部分空间,程序会崩溃。如:int* p = (int *)malloc(sizeof(int));p++;free(p);3. 忘记释放4. free函数只是释放了内存空间,但不会修改指针本身的值。因此,调用 free 后,指针 p 仍然指向之前分配的内存地址指针设置为 nullptr,以避免出现悬空指针的问题new与operator new的区别new 调用过程1.首先调用operator new 分配内存  2.然后调用对象的构造函数构造对象2. operator new 的实现 ,调用malloc分配内存,成功返回void * 类型指针,失败返回bad_alloc与malloc区别:  malloc+失败抛异常实现void * operator new(std::size_t size) throw(std::bad_alloc){if (size == 0){size = 1;}void* p;while ((p = ::malloc(size)) == 0){ //采用 malloc 分配空间std::new_handler nh = std::get_new_handler();if (nh)nh();elsethrow std::bad_alloc();}return p;}3. 调用定位new在开辟内存上构造对象void* memory = operator new(sizeof(MyClass));MyClass* myObject = new(memory) MyClass();void* CTest::operator new(size_t size, void* memory){size;std::cout << "执行了类中的重载 placement new 函数。" << std::endl;return pbuffer;}4. new int[10]原理a. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成10个对象空间的申请b. 在申请的空间上执行10构造函数delete 调用过程:1.在空间上执行析构函数,完成对象中资源的清理工作2.调用operator delete数释放对象的空间3. operator delete 释放内存与free区别:1. 不会造成二次释放2. 不会释放部分内存void operator delete (void* pUserData){_CrtMemBlockHeader * pHead;RTCCALLBACK(_RTC_Free_hook,(pUserData,0));if(pUserData== NULL)return;_mlock(_HEAP_LoCK);__TRYpHead=pHdr(pUserData);_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockuse));_free_dbg( pUserData,pHead->nBlockUse); // free__FINALLY_munlock(_HEAP_LOCK);__END_TRY_FINALLYreturn;}4. delete[]原理a.在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理b.调用operator delete[]放空间,实际在operator delete[]中调用operator delete释放空间5.删除定位placement new直接调用对象的析构函数1.malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。2.对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。 由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。3.new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换;malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。4.new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。5.使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算;malloc则需要显式地指出所需内存的尺寸

malloc的内存分配方式:

  • 方式一:通过 brk() 系统调用从堆分配内存
  • 方式二:通过 mmap() 系统调用在文件映射区域分配内存;
  • 如果用户分配的内存小于 128 KB,则通过 brk() 申请内存;
  • 如果用户分配的内存大于 128 KB,则通过 mmap() 申请内存;

        malloc() 在分配内存的时候,并不是老老实实按用户预期申请的字节数来分配内存空间大小,而是会预分配更大的空间作为内存池

        malloc(1) 实际上预分配 132K 字节的内存。因为要加上内存块的描述信息.

  • malloc 通过 brk() 方式申请的内存,free 释放内存的时候,并不会把内存归还给操作系统,而是缓存在 malloc 的内存池中,待下次使用
  • malloc 通过 mmap() 方式申请的内存,free 释放内存的时候,会把内存归还给操作系统,内存得到真正的释放.

这篇关于面试十三、malloc 、calloc、realloc以及new的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/925191

相关文章

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华

Python中的魔术方法__new__详解

《Python中的魔术方法__new__详解》:本文主要介绍Python中的魔术方法__new__的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、核心意义与机制1.1 构造过程原理1.2 与 __init__ 对比二、核心功能解析2.1 核心能力2.2

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

CSS Padding 和 Margin 区别全解析

《CSSPadding和Margin区别全解析》CSS中的padding和margin是两个非常基础且重要的属性,它们用于控制元素周围的空白区域,本文将详细介绍padding和... 目录css Padding 和 Margin 全解析1. Padding: 内边距2. Margin: 外边距3. Padd

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法

分辨率三兄弟LPI、DPI 和 PPI有什么区别? 搞清分辨率的那些事儿

《分辨率三兄弟LPI、DPI和PPI有什么区别?搞清分辨率的那些事儿》分辨率这个东西,真的是让人又爱又恨,为了搞清楚它,我可是翻阅了不少资料,最后发现“小7的背包”的解释最让我茅塞顿开,于是,我... 在谈到分辨率时,我们经常会遇到三个相似的缩写:PPI、DPI 和 LPI。虽然它们看起来差不多,但实际应用

GORM中Model和Table的区别及使用

《GORM中Model和Table的区别及使用》Model和Table是两种与数据库表交互的核心方法,但它们的用途和行为存在著差异,本文主要介绍了GORM中Model和Table的区别及使用,具有一... 目录1. Model 的作用与特点1.1 核心用途1.2 行为特点1.3 示例China编程代码2. Tab