上海最新新闻头条,阳城seo排名,广西建设厅官网证件查询,wordpress随机文章插件文章目录 C从源代码到可执行程序经过什么步骤静态链接和动态链接类的对象存储空间C的内存分区内存池在成员函数中调用delete this会出现什么问题#xff1f;如果在类的析构函数中调用delete this#xff0c;会发生什么#xff1f; C从源代码到可执行程序经过什么步骤
预处理… 文章目录 C从源代码到可执行程序经过什么步骤静态链接和动态链接类的对象存储空间C的内存分区内存池在成员函数中调用delete this会出现什么问题如果在类的析构函数中调用delete this会发生什么 C从源代码到可执行程序经过什么步骤
预处理预处理主要是对伪指令和特殊符号进行处理将.c文件转为.i文件具体处理如下 宏定义如#define Name TockenString等预编译所要作的是将程序中的全部Name全部用TockenString替换处理所有的条件编译指令如#if、#endif、#ifdef等处理#include预编译指令将文件内容替换到它的位置该过程是递归进行的删除所有的注释//和/**/保留所有的#pragma编译器指令编译器需要使用它们添加行号和文件标识便于编译时编译器产生调试用的行号信息该行号也是编译时产生编译错误或警告能够显示行号 编译经过预处理后的代码进行一系列词法分析、语法分析、语义分析及优化被编译器转换为汇编语言代码。汇编将汇编代码转变成机器可以执行的指令(机器码文件)链接将不同的源文件产生的目标文件进行链接从而形成一个可以执行的程序。链接分为静态链接和动态链接
静态链接和动态链接 静态链接和动态链接两者最大的区别在于链接的时机不一样静态链接是在形成可执行程序前而动态链接的进行则是在程序执行时 静态链接 静态链接是在编译时将程序所需的库文件的代码复制并链接到最终的可执行文件中。在静态链接时所有用到的库函数的代码都被复制到可执行文件中使得可执行文件完全独立不再依赖外部的库文件。这意味着在运行时不需要加载额外的库文件因此可执行文件的大小较大。 静态链接的步骤包括编译源代码文件、将对象文件打包成静态库文件通常以.lib或.a为扩展名然后将静态库文件链接到最终的可执行文件中。可执行文件中包含了所有用到的库函数的代码因此可以独立地在任何支持相应系统架构的计算机上运行。 静态链接优缺点 优点代码装载速度快执行的时候运行速度快 缺点一是浪费空间因为每个可执行程序中对所有需要的目标文件都要有一份副本所以可能同一个目标文件都在内存存在多个副本另一方面就是更新比较困难因为每当库函数的代码修改了这个时候就需要重新进行编译链接形成可执行程序。 动态链接 动态链接是在运行时将程序所需的库文件的代码与程序代码进行动态链接形成最终的可执行文件。 动态链接的步骤包括编译源代码文件、将对象文件打包成共享库文件通常以.dll或.so为扩展名然后在运行时动态地加载共享库文件并将程序与共享库连接在一起。 动态链接优缺点 优点节省内存适用于大规模的软件开发使开发过程独立、耦合度小便于不同开发者和开发组织之间进行开发和测试更新也比较方便更新时只需要替换原来的目标文件而无需将所有的程序再重新链接一遍把链接推迟到了程序运行时所以每次执行程序都需要进行链接所以性能会有一定损失。
类的对象存储空间
非静态成员的数据类型大小之和编译器加入的额外成员变量如虚表指针
C的内存分区 内存可以整体分为三个部分栈区、堆区、静态常量区。栈区主要存储的是局部变量和函数参数C语言当中malloc、calloc、realloc、C当中的new申请的空间基本是在堆区堆区也被称为自由存储区静态常量区有两个主要的标记static定义的变量和字符串常量。静态常量区细分可以是数据段和代码段全局变量和static变量存放在数据段字符串常量这种只读常量放在代码段。 栈又叫堆栈存储非静态局部变量、函数参数、返回值等等栈是向下增长的。 内存映射段是高效的I/O映射方式用于装载一个共享的动态内存库。用户可使用系统接口创建共享内存做进程间通信。 堆用于程序运行时动态内存分配堆是可以向上增长的。 数据段存储全局数据和静态数据。 代码段存储可执行的代码和只读常量。
内存池
内存池是池化技术的应用之一池化技术就是程序先向系统申请过量的资源资源由程序自己来管理以备不时之需。之所以一次提前申请过量的资源是因为每次申请该资源都有较大的开销不如提前申请放着程序自己管理这样使用的时候就非常方便大大提高程序的运行效率内存池是指程序预先从操作系统申请一块足够大的内存此后当程序中需要申请内存的时候不是直接向操作系统申请而是直接从内存池中获取同理当程序释放内存的时候并不真正将内存返回给操作系统而是返回内存池。当程序退出(或者特定时间)时内存池才将之前申请的内存真正释放。内存池通常是由一块连续的内存区域组成被划分为大小相等的块或者按照一定的规则进行划分。当需要分配内存时从内存池中取出一个合适大小的块当内存不再使用时将其放回内存池以供后续的再利用。内存池管理者会维护一个空闲块链表用于记录可用的内存块这样在分配内存时可以快速找到合适大小的块。内存池主要解决的问题提高内存分配的效率减少了频繁的内存分配和释放操作内存碎片问题内存池通过固定大小的块进行内存分配避免了因为不同大小的内存块交替使用而导致的内存碎片问题提高程序性能通过减少内存分配和释放的次数内存池可以显著提高程序的性能和响应速度。
在成员函数中调用delete this会出现什么问题
delete this 相当于“类对象的自杀”delete之后类对象被释放掉但是只要不涉及到this的指针任何函数调用都还可以正常进行为什么呢根本原因在于内存模型在类对象的内存空间中只有数据成员和虚函数表指针并不包含类的成员函数类的成员函数单独放在代码段中。在调用成员函数时隐含传递一个this指针告诉成员函数是哪个对象在调用它。虽然delete之后类对象被释放掉在成员函数中调用delete this会出现什么问题为什么不是指针错误或者无访问权限令系统崩溃的问题呢因为释放掉的内存空间并不是立刻被回收的所以有可能还是可以访问的只是值是不确定的。当访问或操作数据成员的时候可能得到一串未初始化的随机数访问虚函数表就会出现不可预期的问题。为什么是不可预期的问题上面解释了内存空间并不是马上被回收到系统中此时这段内存还是可以访问的但是其中的值却是不确定的当你获取数据成员可能得到的是一串很长的未初始化的随机数访问虚函数表指针无效的可能性非常高造成系统崩溃。
如果在类的析构函数中调用delete this会发生什么
会导致堆栈溢出。因为delete的本质是“为将被释放的内存调用析构函数然后释放内存”。delete this会去调用本对象的析构函数而析构函数中又调用delete this形成无限递归造成堆栈溢出系统崩溃.