当前位置: 首页 > news >正文

安居网站建设网站设计概述

安居网站建设,网站设计概述,给别人做网站怎么赚钱吗,asp网站时间代码最近在开发的时候#xff0c;特别是遇到关于跨DLL申请对象、指针、内存等问题的时候遇到了这么一个问题。 问题 跨DLL能不能调用到DLL中提供的单例#xff1f; 问题比较简单#xff0c;就是我现在有一个进程A#xff0c;有DLL B DLL C#xff0c;这两个DLL都依赖DLL D的…最近在开发的时候特别是遇到关于跨DLL申请对象、指针、内存等问题的时候遇到了这么一个问题。 问题 跨DLL能不能调用到DLL中提供的单例 问题比较简单就是我现在有一个进程A有DLL B DLL C这两个DLL都依赖DLL D的单例这个时候如果A调用了DLLB 和 DLL C那么B和C能否正确引用到这个指定的单例 其实这个问题我心中想的是可以使用这个进程的但是在实际开发中我们却有了争议有的人认为可以有的人认为不可以但是我对这个内存的所有权一直不太清楚所以这也算是给自己一个解惑一个交代。这篇文章也是我边查资料边写的有引用很多文章主要是为了引出结论和一些别的问题。 聊C/C的动态内存管理的内容之前我们先来了解一下进程中的内存分区如上所示。我们可以通过查看程序的完整启动过程去看这些内存分区。 内存分区 在C中将操作系统分配给程序的内存空间按照用途划分了代码段、数据段、栈、堆几个不同的区域每个区域都有其独特的内存管理机制。 代码区 只存代码本身几乎不需要考虑 代码区是用于存储程序代码的区域代码段在程序真正执行前就被加载到内存中在程序执行期间代码区内存不会被修改和释放。由于代码区是只读的所以会被多个进程共享。在多个进程同时执行同一个程序时操作系统只需要将代码段加载到内存中一次然后让多个进程共享这个内存区域即可。 数据段 纯粹的数据几乎不用考虑 数据段用于存储静态全局变量、静态局部变量和静态常量等静态数据。在程序运行期间数据段的大小固定不变但其内容可以被修改。按照变量是否被初始化。数据段可分为已初始化数据段和未初始化数据段。 栈 存放局部变量和函数调用。局部变量访问出错和函数死循环往往会导致stacks overflow。 C中函数调用以及函数内的局部变量的使用都是通过栈这个内存分区实现的。栈分区由操作系统自动分配和释放是一种后进先出的一种内存分区。每个栈的大小是固定的一般只有几MB所以如果栈变量太大或者函数调用嵌套太深容易发生栈溢出stack overflow。 堆 一般就是我们new出来的指针是一些内存空间。当内存地址所有权不明或者内存出错就容易出现堆损坏问题。 用于存放在程序运行时被动态分配的内存段。堆的大小不固定可以动态增加和减少。使用malloc()等函数动态分配内存到堆上使用free()等函数释放对应的动态分配内存。堆的最大容量受限于系统中有效的虚拟内存。 栈和堆 区别 1、申请方式栈的空间由操作系统自动分配和释放堆上的空间需要程序员使用malloc\free手动分配和释放。如果不释放会造成内存泄漏。 2、申请大小限制和效率栈的空间时有限的在linux中使用 ulimit -s 指令 可以看到看到栈的容量为8M。栈区以先进后出的方式自动分配时连续的内存单元效率高。 堆的大小受限与系统中有效的虚拟内存大小系统是用链表来存储空闲的内存块是不连续的。因此堆的空间分配比较灵活但容易产生内存碎片相对来讲对效率低。 对于一个程序而言大概的模型是这样的 以启动Windows系统中的exe程序为例 当我们双击某个exe程序或者通过桌面等快捷方式去启动一个exe程序时就进入exe程序的启动过程。 程序启动时系统首先会将exe主程序依赖的所有的dll库文件包括exe程序自带的dll以及exe程序依赖的系统dll都加载到进程空间中这些dll二进制文件中存放的是可执行的二进制机器代码即汇编代码机器码与汇编代码等价的汇编代码是机器码的助记符都加载到进程的代码段的内存区中。 待所有依赖的dll模块都加载到进程空间后最后才会将exe主程序加载到进程空间中。然后去启动C/C的运行时库紧接着去给全局变量分配内存并执行全局变量的初始化操作此处对应的就是全局内存区。然后才会进入到main函数程序才能真正的启动并运行起来。 进入到函数中就会从所在线程的栈内存上给函数的局部变量分配栈内存这就是我们讲的栈内存。当执行到malloc或new等代码时申请的内存就是堆内存。 回到问题 这个问题其实实际上还没有涉及到内存所有权问题但是我觉得可以当作一个引子 static变量的唯一性是动态库级别的不同库包含同一截代码的话就会有多份static实例。出现问题的情况往往是这截代码是实现在头文件里的所以被不同模块引用时就生成了多份代码。解决办法就是按照一般DLL导出接口的规则在获取static变量的地方 1.对于实现单例的dll使用dllexport。对于MSVC来说就是__declspec(dllexport)对于GCC/clang就是__attribute__ ((dllexport)) 2.对于引用单例的dll使用dllimport。对于MSVC/clang来说就是__declspec(dllimport)对于GCC/clang就是__attribute__ ((dllimport))这样就只有一份了。 所以跨DLL的单例模式是可行的这个静态变量单例对象必须导出否则这个静态对象的实现会在不同的代码头文件引用的过程中一同被申请出来。 解决方案 1.设计代码时选好单例的内存该放在哪然后通过导入导出一解决(MSVC上导入导出使_declspec(dllimport)和_declspec(dllexport)类比extern变量一)。比如单例打算放在动态链接库A中那就在生成动态库A的地方的这个static变量导出其他动态链接库°或可执行文件使用的地方导入。 2.搞个统一的地方大家的单例共同注册到一起用的时候拿出来。 tips: Windows使用注意事项 要求使用MD/MDd而不是MT/MTd反正至少保证要保证exe和所有dll使用同一间使用同一个crtheap堆否则exe和不同dll间都有各自的crtheap堆而new和delete需要在同一堆中配套执行。慎用virtual析构函数不能为virtual函数。因为当析构函数为virtual函数时如果单例由dll1加载而dll2在dll1卸载之后如果还在使用那析构时调virtual的析构函数会去查虚函数表而虚函数表是由dll1创建的会引发崩溃。其他虚函数也涉及虚函数表因此若要使用虚函数那么除非能保证dll的卸载顺序否则不要使用热卸载。事实上全局单例的管理交由单例框架来实现后析构函数是否使用virtual都不会产生泄漏因为单例框架构造和析构时使用的都是具体的全局单例类而不会是它们的基类。单例全为懒加载直到GetReference的时候才真正实例化单例对象需要注意全局单例没有保证多线程间安全因此在单例实例化/动态库首次获取单例时都是线程不安全的。若在SingletonManager.cpp的Count/Obtain/Release函数中使用std::mutex加锁能够实现单例获取的安全但实例化过程(创建过程)仍是线程不安全的。 下一期来聊聊关于跨DLL引用DLL的时候导致的所有权问题
http://www.hkea.cn/news/14375272/

相关文章:

  • asp net做网站单位建设网站需要的材料
  • 有什么值得做的网站怎么设计网站页面
  • 宁波网站推广优化公司怎么样网站建设合同的要素
  • 怎么创建免费自己的网站平台域名备案 填写网站信息
  • 基金网站建设皖icp备 网站建设
  • 通过网站做外贸四川省城乡住房与建设厅网站首页
  • 使用wordpress搭建网站代理平台有哪些
  • 临沂品牌网站建设公司中信建设有限责任公司地址
  • 做软件需要网站有哪些做违法网站会怎样
  • 如何申请我的网站网络安全建设方案
  • 网站插件 wordpress长春老火车站
  • 廊坊公司网站建设职校网站模板
  • 嘉兴企业网站排名替换wordpress为QQ头像
  • 网站开发 价格海外广告推广公司
  • 广州番禺网站公司网页设计代码为什么没有颜色
  • 营销型网站的分类摄影设计思路
  • 黄冈网站推广下载wordpress主题Tendor
  • 广州网站建设哪家技术好哈尔滨免费自助建站模板
  • 西宁做网站的公司优购物官方网站手机
  • 东莞市品牌网站建设平台建设广州公司网站
  • 搭建网站案例徐州网站制作如何定位
  • 北京网站制作最新教程什么网站做专利检索报告
  • 虹口 教育 网站建设互联网营销师培训方案
  • 免费建设音乐网站中国网站备案取消
  • 网站关键词在线优化网站名字怎样做版权
  • 在因特网上建设网站可选择的方案有做网站公司松江
  • 做网站的大公司都有哪些seo入门培训
  • 平台网站怎么优化网站建设技术员保密协议
  • 厦门网站建设工作需求不明确的软件开发模型
  • 在网上做软件挣钱的网站注册贸易公司流程及费用