64、C++源文件从文本到可执行文件经历的过程
一般分为预处理、编译、汇编、链接四个阶段
(1)预处理阶段:对源代码文件中包含的头文件、预编译语句(宏定义)进行分析和替换,生成编译文件
(2)编译阶段:将编译文件转换成汇编代码,生成汇编文件
(3)汇编阶段:将汇编文件转化成机器码,生成可重定位目标文件
(4)链接阶段:将多个目标文件及所需要的库连接成最终的可执行目标文件
65、include头文件的顺序以及双引号“ ”和尖括号<>的区别
(1)include头文件的顺序: 如果头文件之间没有关联,那么所有的头文件只要在变量声明或者定义之前include就好,如果头文件之间相互耦合,并且没有在头文件进行相应的include,在cpp文件就要注意,到底哪个头文件该先include。
(2)双引号和尖括号的区别:
一般来说,双引号是用来include自定义的头文件,而尖括号是用来include自带库的头文件。另外编译器预处理阶段查找两者的头文件路径不一样的: #1 对于使用双引号包含的头文件,查找顺序为: (a)当前头文件目录
(b)编译器设置的头文件路径(编译器可使用-I显示指定搜索路径)
(c)系统变量CPLUS_INCLUDE_PATH/C_INCLUDE_PATH指定的头文件路径
#2 对于使用尖括号包含的头文件,查找头文件的路径顺序为:
(a)编译器设置的头文件路径(编译器可使用-I显示指定搜索路径)
(b)系统变量CPLUS_INCLUDE_PATH/C_INCLUDE_PATH指定的头文件路径
66、C++的内存管理是怎么样的
在C++中采用虚拟内存分布去管理内存,共分为代码段、数据段、BSS段、堆区、栈区以及文件映射区六部分
(1)代码段:包括只读存储区和文本区,其中只读存储区存储字符串常量,文本区存储程序的机器代码。
(2)数据段:存储程序中以初始化的全局变量和静态变量
(3)bss段:存储未初始化的全局变量和静态变量,以及所有被初始化为0的全局变量和静态变量
(4)堆区:调用new/malloc函数时在堆区动态分配内存,同时需要调用delete/free来手动释放申请的内存
(5)栈区:使用栈空间存储函数的返回地址、参数、局部变量、返回值
(6)映射区:存储动态链接库以及调用mmap函数进行文件映射
67、什么是内存泄漏(memory leak)?如何去判断有没有内存泄漏?
(1)内存泄漏
内存泄漏是指由于疏忽或者错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏并不是真正意义上的内存物理上的消失,而是指程序失去了对该段内存的控制,因此造成内存浪费。
(2)内存泄漏的分类
#1 堆内存泄漏
堆内存是指通过malloc,new等从堆中分配出来的内存,如果这部分内存没有通过free或者delete进行释放,那么就会造成堆内存泄漏
#2 系统资源泄漏
主要是指系统分配的资源,比如套接字,文件描述符等,没有使用相应的函数释放掉,导致系统资源的浪费
(3)判断内存泄漏
一方面,可以使用内存泄漏检查工具Valgrind、mtrace,不过这些工具必须在Linux环境下使用;另一方面可以在写代码时候添加内存申请和释放的统计功能,统计一下当前申请和释放的内存是否一致,以此来判断内存是否泄漏。
68、什么时候会发生段错误?
段错误通常发生在访问非法内存地址的时候,具体来说分为以下几种情况: (1)使用野指针
(2)试图修改字符串常量的内容
69、堆和栈有什么区别?
(1)分配和管理的方式不同:
堆是动态分配的,其空间的分配和释放都依赖与程序员自身
栈是由编译器自动管理的,其分配方式有两种:静态分配由编译器完成,比如局部变量的分配;动态分配由alloca()函数进行分配,但是会由编译器释放
(2)生长的方向不同
堆是向内存地址增加的方向增长的,从内存的低地址向高地址方向增长;
栈是向内存地址减小的方向增长的,从内存的高地址向低地址方向增长;
(3)申请大小限制不同
栈顶和栈底都是预设好的,大小固定;
堆是不连续的内存区域,其大小可以灵活调整;
(4)产生的碎片不同
对于堆来说,频繁使用new/delete或者malloc/free会造成内存空间的不连续,产生大量的碎片,使程序效率降低
对于栈来说,不存在内存碎片的问题,因为栈具有先进先出的特性
70、静态内存分配和动态内存分配有什么区别?
(1)静态内存分配是在编译时期完成的,不占用CPU资源;动态内存分配是在运行时期完成的,分配和释放需要用CPU资源
(2)静态内存分配是在栈上,而动态内存分配是在堆上
(3)静态内存分配不需要指针或者引用类型的支持,而动态需要
(4)静态内存分配的内存块在编译前就已经确定了,而动态分配是按需分配
(5)静态内存分配是把内存的控制权交给了编译器,而动态内存分配是把内存的控制权交给程序员
(6)静态内存分配的运行效率会比动态内存分配高,动态内存分配不当可能会造成内存泄漏