动态内存管理面试夺命六连问?

1 程序运行起来后,内存被分为几个区域?操作系统为什么要对内存分这些区域?

答:程序运行起来后,内存被分为内核态和用户态,内核态控制操作系统的主要运行,而用户态是用户自己定义实现的。其主要分布如下:
在这里插入图片描述

  • 内核空间放操作系统的代码以及数据的,只要操作系统能够进行访问的话,必须通过专门的API函数来进行访问。
  • :存放和函数调用相关的数据,比如局部变量,参数,一些寄存器的信息。
  • 内存映射段:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
  • :程序员动态申请的空间,堆是向上增长的。
  • 数据段全局变量和static修饰的变量
  • 代码段:该部分的内容是不允许被修改的代码和常量
    通俗的理解是不同的区域,功能是不一样的,方便操作系统管理这些数据,比如房子中客厅是休息的,卧室是睡觉的,厨房是做饭的,卫生间是上厕所的,阳台是晾衣服的等。

2 什么是动态内存?

答:动态内存是用户自己申请的内容空间,并且在用完之后,是需要由用户动态进行释放的空间。

3 为什么需要进行动态内存申请呢?

答:在内存不同的区域存放不同的是不同的数据,而用户数据能够存放的位置是在堆和栈上,栈是有固定大小的,这就导致用户的数据可能非常大,在栈区中存储不下时,需要更大的内存空间类存储用户的数据,而更大的内存空间用户需要向操作系统来进行获取。栈空间在函数运行时的栈帧随函数运行而创建,随函数的结束而回收,回收之后函数中局部变量的数据就没有意义,但是有些情况下,我们需要将程序运行期间产生的数据带出函数之外,这就需要进行动态内存申请。

4 动态内存申请时,需要注意什么问题?

答:一般在内存申请的时候需要多少申请多少,在使用时,需要越界,用完之后记得及时归还。

5 C语言中是如何进行内存申请的?

  • 必须要包含对应的头文件。
  • 使用动态内存申请的函数:malloc/calloc/realloc。
  • 空间使用完成之后一定要归还:free()。

5.1 malloc/calloc/realloc有什么区别?

5.1.1 相同点

  1. 都是c语言标准的库函数;
  2. 使用的都是必须包含对应的头文件;
  3. 都是用来进行动态内存空间申请的;
  4. 申请的空间都是在堆上;
  5. 申请空间成功后返回空间的首地址,申请空间失败后返回的是NULL,因此在使用之前必须进行判空;
  6. 他们的返回值类型都是void*,在使用时必须要进行强制类型转换;
  7. 用完之后一定要用free来进行释放。

5.1.2不同点

void* malloc(size_t size) ;
  1. 参数是所有需要空间的字节数;
  2. 返回值是void*,使用时必须要进行强制类型转换;
  3. 申请成功,返回空间的首地址,申请失败返回NULL,因此在使用时,必须要进行判空;
  4. 使用完成后,一定要使用free来进行释放。
void* calloc(size_t num, size_t size);
  1. num表示参数的个数,size表示单个元素的大小;
  2. calloc会对申请的空间使用0来初始化。
void* realloc(void* ptr, size_t size);

主要功能:将ptr指向的空间重新调整到size个字节,完成之后返回空间的首地址,返回值与一些其他的信息(比如判空,释放等)与malloc相同。

  1. 如果ptrs是空:功能与malloc类似,直接申请size个字节返回即可;
  2. 如果ptr非空:将ptr指向的空间重新调整到size字节,完成后返回空间的首地址。
    在这里插入图片描述

6 C++为什么要再给自己的一套动态内存申请的方式呢?

因为malloc和free是C语言中标准的库函数,但C语言内存管理方式在C++可以继续使用,但有些地方就无能为力而且使用起来比较麻烦,并且malloc在创建对象类型空间期间不会调用构造函数。free在释放对象类型空间期间不会调用析构函数。因此C++提出了自己的内存管理方式,通过new和delete操作符进行动态内存管理。

猜你喜欢

转载自blog.csdn.net/aaaaauaan/article/details/109067602