当前位置:网站首页>二阶段提问总结
二阶段提问总结
2022-08-03 05:23:00 【纸鸢805】
1.堆与栈实际上是操作系统对进程占用的内存空间的两种管理方式.
主要有如下几种区别:
(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;
(2)空间大小不同。每个进程拥有的栈大小要远远小于堆大小。理论上,进程可申请的堆大小为虚拟内存大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;
(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。
(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有 2 种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca()函数分配,但是栈的动态分配和堆是不同的,它的动态分配是由操作系统进行释放,无需我们手工实现。
(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。
(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。
从以上可以看到,堆和栈相比,由于大量malloc()/free()或new/delete的使用,容易造成大量的内存碎片,并且可能引发用户态和核心态的切换,效率较低。栈相比于堆,在程序中应用较为广泛,最常见的是函数的调用过程由栈来实现,函数返回地址、EBP、实参和局部变量都采用栈的方式存放。虽然栈有众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,主要还是用堆。
无论是堆还是栈,在内存使用时都要防止非法越界,越界导致的非法内存访问可能会摧毁程序的堆、栈数据,轻则导致程序运行处于不确定状态,获取不到预期结果,重则导致程序异常崩溃,这些都是我们编程时与内存打交道时应该注意的问题。
2.拷贝构造
拷贝构造函数就是用已存在的对象来初始化另一个对象。
在C++中,下面三种对象需要拷贝的情况。因此,拷贝构造函数将会被调用。 1). 一个对象以值传递的方式传入函数体 2). 一个对象以值传递的方式从函数返回 3). 一个对象需要通过另外一个对象进行初始化
浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
拷贝构造函数,用一个对象来初始化另一个对象,是在类对象定义的时候起作用。 赋值函数,通过把一个对象赋值给另一个对象来改变对象,是在被赋值对象定义以后通过调用赋值函数起作用。 2个函数的结果一样,但使用的地方不一样,
3.类模板和模板类
所谓类模板,实际上是建立一个通用类,其数据成员、成员函数的返回值类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模板定义对象时,系统会实参的类型来取代类模板中虚拟类型从而实现了不同类的功能。
4.静态库动态库
根据链接时期不同,库分为静态库和动态库。静态库是在程序编译时链接的,动态库是在程序运行时链接的。
目前默认使用动态库,虽然会比较慢一点但是以现在的硬件来说影响不大,好处更多。
链接静态库其实从某种意义上来说也是一种粘贴复制,只不过它操作的对象是目标代码而不是源码而已。因为静态库被链接后库就直接嵌入可执行文件中了,这样就带来了两个问题。
1. 首先就是系统空间被浪费了。这是显而易见的,想象一下,如果多个程序链接了同一个库,则每一个生成的可执行文件就都会有一个库的副本,必然会浪费系统空间。
2. 一旦发现了库中有bug,挽救起来就比较麻烦了。必须一一把链接该库的程序找出来,然后重新编译。
而动态库的出现正弥补了静态库的以上弊端。因为动态库是在程序运行时被链接的,所以磁盘上只须保留一份副本,因此节约了磁盘空间。如果发现了bug或要升级也很简单,只要用新的库把原来的替换掉就行了。
那么,是不是静态库就一无是处了呢?
答:非也非也。想象一下这样的情况:如果你用libpcap库编了一个程序,要给被人运行,而他的系统上没有装pcap库,该怎么解决呢?最简单的办法就是编译该程序时把所有要链接的库都链接它们的静态库,这样,就可以在别人的系统上直接运行该程序了。
正因为动态库在程序运行时被链接,故程序的运行速度和链接静态库的版本相比必然会打折扣。然而瑕不掩瑜,动态库的不足相对于它带来的好处在现今硬件下简直是微不足道的,所以链接程序在链接时一般是优先链接动态库的,除非用-static参数指定链接静态库。
5.ffmpeg 解码编码的作用
编码的目的:
是为了压缩媒体数据。有别于通用文件数据的压缩,在图像或音频压缩的时候,可以借助图像特性(如前后关联、相邻图块关联)或声音特性(听觉模型)进行压缩,可以达到比通用压缩技术更高的压缩比。
解码的目的:
可以把目标文件或者摄像头等获取图像设备输入的图像数据进行获取转为想要的数据格式,可进行显示。
6.指针的偏移
指针的偏移实际上就是根据指针的类型来确定一个指针所占的地址空间大小,偏移一个实际上就是偏移 sizeof(数据类型) 个字节。c 当中各数据类型占据字节。
注: 一字节等于8bit;
64位编译器:
char/unsigned char :1字节
char *:8字节
short int:2字节
int/unsigned int:4字节
long int:8字节
float:4字节
double:8字节
long long:8字节
long double:16字节
边栏推荐
猜你喜欢
当我们在看Etherscan的时候,到底在看什么?
Leetcode刷题——128. 最长连续序列
Oracle 密码策略详解
pta a.1030的dijkstra+DFS方法
Execute the mysql script file in the docker mysql container and solve the garbled characters
icebreaker的垃圾话学习指南
docker mysql 容器中执行mysql脚本文件并解决乱码
TypeError: Cannot read property ‘xxxx‘ of undefined的解决方法
网卡软中断过高问题优化总结
block底层探索
随机推荐
动态规划笔记
动漫 吞噬星空
中国磷化铟晶圆行业发展前景与投资规划分析报告2022~2028年
A-B数对问题|UPC-Count Interval|洛谷-P1102A-B数对
【DC-4 Range Penetration】
Haproxy服务监控
TypeError: Cannot read property ‘xxxx‘ of undefined的解决方法
令人愉快的 Nuxt3 教程 (二): 快速轻松地搭建博客
php连接数据库脚本
Apache2-XXE vulnerability penetration
The ` monorepo ` ` hoist ` mechanism lead to the change of the loading configuration file path
C# 数组之回溯法
中国生产力促进中心”十四五”规划与发展规模分析报告2022~2028年
理论上的嵌入式跑马灯
嵌入式实验三(代码几乎都要改才能运行)
SAP HANA 新增一列时报错详解
【源码解读】你买的NFT到底是什么?
[Rebound shell and privilege escalation]
Hook初探索
中国生物降解塑料行业市场运营态势及发展趋势研究报告2022~2028年