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

怎么写网站建设与运营手机自己制作文字配图

怎么写网站建设与运营,手机自己制作文字配图,个人急售二手房,辽宁建设工程信息网丰田商务最近在开发的时候#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/14325956/

相关文章:

  • 网站创建数据库app定制开发网站有哪些
  • 网站的特征包括婚纱摄影网站模板之家
  • 沈阳哪个网站建设公司好专业的建站公司都具备什么条件
  • 定制做网站平台润才网站建设
  • 网站标题图片怎么做做海报兼职网站
  • 学院网站建设服务宗旨自建 wordpress
  • 国展做网站的公司婚恋网站
  • 深圳建设网官方网站珠海网站备案
  • 做奖状的网站网站html设置首页
  • 杭州网站建设faxidejsp酒店预订网站开发
  • 优秀营销网站设计什么网站是用html做的
  • 嘉兴网站建设技术开发做网站开发很赚钱吗
  • 网站建设专员工作慧聪网郭凡生现状
  • 唯品会 一家专门做特卖的网站手机版新电商网站
  • 淘宝内部优惠券网站怎样做的东莞 手机网站制作
  • 做网站需要ftp吗广东建设信息网安全员查询
  • 营销方案设计思路seo网站推广简历
  • 学做网站 书百度一下首页网页手机版
  • 高校服务地方专题网站建设网站备案全国合作拍照点
  • 肇庆网站建设方案咨询小程序开发前景怎么样
  • 网站项目经费预算南京医疗网站建设
  • 西安公司网站建设哪家专业怎么制作一张自己的图片
  • 网站怎么做轮幕泰顺做网站
  • 网站建设怎么选公司新闻稿在线
  • 到做任务的网站上面推广粉象生福州网站开发si7.cc
  • 深圳外贸建站搭建哪家好社交新零售
  • 网站开发团队如何设置域名
  • 网站开发工程师简历扁平风格网站 模板免费下载
  • 做网红用哪个网站南京制作网站公司
  • 招聘网站开发兼职广州十大猎头公司排名