美文网首页
项目中内存泄漏、不正规编程等各种问题

项目中内存泄漏、不正规编程等各种问题

作者: WilsonLoo | 来源:发表于2020-10-10 11:48 被阅读0次

一、dll间调用顺序不明朗,导致资源释放错乱

修正【正常关服】时资源回收异常的问题。
项目大量使用dll进行组件化设计,跨dll 间资源的不恰当传递和回收方式 都会引起问题。在 GameServer 关服时就出现了资源回收异常,表现为:
在 NFGameServerNet_ServerPlugin.dll 创建了一个【资源R】 供 NFUrlPlugin.dll 使用,
应该在关服时 由 NFGameServerNet_ServerPlugin.dll 回收,但是NFGameServerNet_ServerPlugin.dll  先进行卸载, NFUrlPlugin.dll 卸载时无法找到 【资源R】的正确回收器,进而会出现 Access Violation at Address(地址访问冲突)。

按照如下的dll配置循序:

配置的dll加载与卸载顺序

PluginNameMap NFCPluginManager::mPluginNameMap;
PluginNameMap NFCPluginManager::mPluginNameMapTwo;
虽然原有代码有两个类成员的"意图可能"是为了控制dll的加载卸载顺序的,但是没有写对(在不明朗原有代码意图的情况下,尽量少修改原有的代码,我用新的代码实现了)。

二、dll的对象管理

这个比较基础,也是接触dll 的程序员都需要掌握的,例如通过C语言的 extern, 还是C++的 dllimport/dllexport 方式;如果暴露类可能需要使用面向接口编程,类内部有成员变量,也要考虑其可暴露性。STL作为参数传递时,要考虑器兼容性,因为不同版本的C++标准实现的 STL都不一样,此时一般不作为可暴露参。

三、恶心的资源回收问题

多个dll之间的资源维护, dll-A 创建资源 供 dll-B 使用并持有该资源,在 dll-B 里直接对该资源进行了回收,这是不正确的,因为不同的 dll/exe 分属不同的模块,其内部的数据、堆栈也是相互独立,资源的创建与释放必须在同一个 dll/exe 模块内,否则会出现 【地址访问冲突】Access Violation at Address。

C语言的做法是 dll-A 通过malloc 创建对象,供dll-B 使用并持有该资源,进行回收时,dll-B 将该资源交回给dll-A 进行正确的资源回收。

C++ 语言的做法是 dll-A 通过new 创建对象,并通过引用计数(智能指针)对该对象进行包装、绑定资源回收函数,dll-B 使用并持有该资源,因为使用了引用计数,在dll-B 卸载时无需显示调用资源回收相关的函数,完完全全有引用计数自动处理。

四、在开发期间,适当提高编译警告,尽早规避问题

1、解决方案的CMakeLists.txt 只在Unix 环境下开启了 全级别的警告级别 -Wall, Windows的vs环境则默认为 /W1(建议调整为不比 Unix的警告级别, 因为我们都在windows下进行开发,应该尽早在开发期间发现问题,尽量避免出现在不同环境下编译结果不一致的情况);

2、将编译警告C4715(warning C4715:not all control paths return a value,不是所有的控件路径都返回值)强制改为 Error错误级别; 因为如果一个路径没有直接指明返回值的话, 编译器会根据返回值类数据类型的默认值,但是不同编译器对默认值的生成不一样,一些是0xcdcdcdcd, 一些是0,即使是同一编译器的不同版本的实现也会不一致;会出现一种潜在性的问题, 在windows下编译运行正常, 但在其他编译器编译运行后,却出现了异常!例如:

3、NFCMysqlDriverManager::AddMysqlServer() 内部出现了资源泄漏: 没有对new NFCMysqlDriver对象进行回收!没有正确使用多态(基于继承的运行时多态),PT项目的编程模式是【面向接口编程】,如果 NFIMysqlDriver/NFINet 基类没有提供virtual 析构函数,编译器会自动构造【默认非virtual析构函数】,在进行delete操作时,就会只调用 NFIMysqlDriver 的【默认非virtual析构函数】,子类(具体实现类)的析构函数不会被调用/部分成员函数没有释放,进而造成资源泄漏。在vc++下有 /Wall: C4265 编译警告 class has virtual functions, but destructor is not virtual instances of this class may not be destructed correctly,gcc 下/Wall 是 deleting object of abstract class type ‘*****’ which has non-virtual destructor will cause undefined behaviour [-Wdelete-non-virtual-dtor], 也建议将此警告强制为 错误error。

相关文章

  • 项目中内存泄漏、不正规编程等各种问题

    一、dll间调用顺序不明朗,导致资源释放错乱 修正【正常关服】时资源回收异常的问题。项目大量使用dll进行组件化设...

  • Xcode调试工具

    一.静态内存分析工具 编译阶段查找内存泄漏等问题 1.常见内存泄漏问题 常见的内存泄漏除了循环引用,CoreFou...

  • 快速串讲---JVM内存的区域划分

    目的 快速定位JVM内存泄漏或者溢出等问题。 面试基础题,加分项。 程序计数器(Program Counter R...

  • 内存检测问题

    1.如何检测内存问题 内存泄漏:在基于Java的运行中,内存泄漏是一种编程错误,它会导致应用程序对已经不需要再使用...

  • 如何检测内存泄漏

    1.如何检测内存问题 内存泄漏:在基于Java的运行中,内存泄漏是一种编程错误,它会导致应用程序对已经不需要再使用...

  • 轻松搞定内存泄露的产生,检测和解决

    以前MRC的下由于缺少release等会经常造成内存泄漏问题,如今在ARC下内存泄漏的问题已经减少了很多,但是还有...

  • C/C++内存泄漏及检测

    “该死系统存在内存泄漏问题”,项目中由于各方面因素,总是有人抱怨存在内存泄漏,系统长时间运行之后,可用内存越来越少...

  • C/C++编程知识:内存泄漏及检测

    “该死系统存在内存泄漏问题”,项目中由于各方面因素,总是有人抱怨存在内存泄漏,系统长时间运行之后,可用内存越来越少...

  • C++ 内存问题汇总

    1.内存泄漏等问题查找方式 不断更新中...

  • 内存泄漏的检测与解决方法

    实训通关第三期 1.如何检测内存问题 内存泄漏:在基于Java的运行中,内存泄漏是一种编程错误,它会导致应用程序对...

网友评论

      本文标题:项目中内存泄漏、不正规编程等各种问题

      本文链接:https://www.haomeiwen.com/subject/bgbdpktx.html