热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

内存泄漏Dump,单键陷阱

原文一:DLL导出习惯以及内存泄漏DumpSUN引擎部分非常习惯使用动态链接库,将各个模块分割开发以便扩展更换。和国内动态库设计不同,SU

原文

一:DLL导出习惯以及内存泄漏Dump

SUN引擎部分非常习惯使用动态链接库,将各个模块分割开发以便扩展更换。

和国内动态库设计不同,SUN的动态导出很少大量使用 EXPORT_DLL 对类和函数进行导出,除了物理系统部分,大部分DLL库仅有一个函数进行导出,多半如下:

extern "C" __declspec( dllexport ) void* Func( ENUM p_eStyle, void* p_pParam ){

   
//BreakPointOnMemoryLeak( 41);

   StartMemoryLeakCheck();

   
switch( p_eStyle )

   { 
case eXXX_1:    m_XXX = new CXXX(); m_XXX->DoSth( p_ppParam ); }

}

利用一个函数,传入两个参数,根据第一个枚举参数进行不同的操作,而第二个参数是根据第一个参数进行强制转换为不同类型的指针已协作进行操作,这是个很狡猾的设定,一个简陋的工厂就这么出现了

这点相信有点设计模式的人就能够简单看懂。

不过,这里的DoSth看似简单,却被SUN程序员用的出神入化,这么一个简单的接口,不仅仅是管理器的生成,连大量的操作都被封装进去了,例如:

// 1:创建管理器功能( 最常见的DLL接口功能 )

CWzBase* pBaseManager = NULL; // CWzBase是CWzAnimationManager的基类

case CW_NEW_WZD_ANIMATION: 

pBaseManager 
&#61; new pBase( static_cast<char*> p_pParam );

return pBaseManager ; // 注意接口函数返回值不是void&#xff0c;而是void*

// 2: 销毁管理器功能

case CW_DELETE_WZD_ANIMATION:

pBaseManager &#61; (CWzBase* )p_pParam;

delete [] pBaseManager;

// 3: 控制功能

case CW_SET_COLOR:

pBaseManager->SetColor( (WzColor*)p_pParam );

// 4: 获取功能

case CW_GET_COLOR:

pBaseManager->GetColor( (WzColor*)p_pParam );

看看如何强悍……一个接口加一个枚举&#xff0c;顶多少接口下去……>_<懒人的福音&#xff1f;

我们还可以值得注意的是

   //BreakPointOnMemoryLeak( 41);

   StartMemoryLeakCheck();

这两句。他们是负责内存检查的。我们看一下源代码先&#xff1a;

#ifdef _DEBUG
#include
#define _CRTDBG_MAP_ALLOC
inline void StartMemoryLeakCheck( void) { _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); }
#define BreakPointOnMemoryLeak( iMemory) _CrtSetBreakAlloc( iMemory)
#else
#define StartMemoryLeakCheck() {}
#define BreakPointOnMemoryLeak {}
#endif

这是使用VC&#43;&#43;的CRT调试堆函数进行内存泄漏检查的方法&#xff0c;恩&#xff0c;简单说明一下

#include 是必须的&#xff0c;调用编译器函数 _CrtSetDbgFlag 和 _CrtSetBreakAlloc 的必需。

#define _CRTDBG_MAP_ALLOC 是CRT库定义的一个宏&#xff0c;我们只需定义该宏&#xff0c;则会在抛出泄漏信息时连同泄漏处所在文件以及行号显示出来。

// 未定义_CRTDBG_MAP_ALLOC宏时&#xff0c;使用_CrtDumpMemoryLeaks()在Debug输出控制台将输出下列信息&#xff1a;

Detected memory leaks!
Dumping objects ->
{18} normal block at 0x00780E80, 64 bytes long.
Data: <> CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

// 定义该宏后&#xff0c;使用_CrtDumpMemoryLeaks()在Debug输出控制台将输出下列信息&#xff1a;

Detected memory leaks!
Dumping objects ->
D:\TestLeak.cpp(30) : {18} normal block at 0x00780E80, 64 bytes long.
Data: <> CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

上下比较&#xff0c;仅仅是多了一个泄漏点的文件名以及行号&#xff0c;建议通常定义该宏。

上面&#xff0c;我们是使用使用_CrtDumpMemoryLeaks()函数进行内存泄漏的输出控制台信息输出。但是这个函数是需要在程序出口时使用的。若我们的程序有多个程序出口&#xff0c;例如&#xff1a;游戏中选择“退出”键&#xff0c;按主窗口右上的X关闭&#xff0c;MessageBox关闭&#xff0c;Alt&#43;F4关闭等多种可能出现程序出口的时候&#xff0c;我们不便在每个出口处调用一次该函数&#xff0c;于是&#xff0c;VC&#43;&#43;提供了一个简便的方法&#xff0c;就是SUN中常用的那一句&#xff1a;

inline void StartMemoryLeakCheck( void) { _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); }

_CrtSetDbgFlag()函数会自动在每个函数出口处设置一个_CrtDumpMemoryLeaks()以检查内存泄漏。

上面的错误信息会在DEBUG模式下&#xff0c;程序运行完毕后&#xff0c;在VC的“输出”窗口显示该Dump的内存块信息。

我们可以看到之前例子中的Dump信息中&#xff0c;有个{18}&#xff0c;这个是内存分配编号&#xff0c;通常来说&#xff0c;一段没有变动的代码&#xff0c;在编译器不变的情况下&#xff0c;内存的分配顺序是确定的&#xff0c;即&#xff0c;它的内存分配编号也是相对固定的&#xff0c;即使是多线程&#xff0c;也会经常性的按顺序分配。

有时CRT并不如我们想象中那么强大&#xff0c;我们无法获得内存泄漏处的源文件名和行号的时候还是常有的&#xff0c;当我们遇到无法映射到源文件的内存泄漏时&#xff0c;我们只好使用_CrtSetBreakAlloc&#xff08;&#xff09;函数来断点&#xff0c;它会监视指定内存分配编号&#xff0c;当程序在分配指定编号的内存块时&#xff0c;该函数会断点断掉&#xff0c;此时我们通过“调用堆栈”可以迅速找到内存泄漏的位置。这就是上面SUN代码中大量

//BreakPointOnMemoryLeak( 41);

的原因了&#xff0c;看来SUN的程序也很是对41编号内存块泄漏头疼了一阵吧&#xff1a;&#xff09;笑。


二&#xff1a;单键陷阱。

我们首先来看SUN中的单键实现

template
class CSingleton
{
public:
static T* s_pSingleton;

CSingleton()
{
   assert( !s_pSingleton);
   int iOffset &#61; ( int)( T*)1 - ( int)( CSingleton *)( T*)1;
   s_pSingleton &#61; ( T*)( ( int)this &#43; iOffset);
}
virtual ~CSingleton()
{
   assert( s_pSingleton);
   s_pSingleton &#61; NULL;
}

static T* GetSingleton( void)
{
   return ( s_pSingleton);
}
};


template
T* CSingleton::s_pSingleton &#61; NULL;

其他的不必说明&#xff0c;我们仅将眼光放在这里int iOffset &#61; ( int)( T*)1 - ( int)( CSingleton *)( T*)1;

这是一句令人迷惑的语法&#xff0c;实际作用是有两点&#xff1a;

1&#xff1a;这个表达式是为了适应不同的编译环境和规则才存在的。我们知道&#xff0c;通常来说&#xff0c;指针的大小是4个字节&#xff08;标准int长度相同&#xff09;&#xff0c;但这个标准根据平台不同&#xff0c;int长度并非确定的。例如&#xff0c;16位系统中指针为2字节&#xff0c;32位为4字节。

2&#xff1a;这个表达式考虑了类多重继承的可能&#xff0c;所以指针寻址的时候是进行的下递增检查。

转:https://www.cnblogs.com/dubingsky/archive/2009/06/23/1509831.html



推荐阅读
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • JUC(三):深入解析AQS
    本文详细介绍了Java并发工具包中的核心类AQS(AbstractQueuedSynchronizer),包括其基本概念、数据结构、源码分析及核心方法的实现。 ... [详细]
  • 字符串学习时间:1.5W(“W”周,下同)知识点checkliststrlen()函数的返回值是什么类型的?字 ... [详细]
  • 在Windows系统中安装TensorFlow GPU版的详细指南与常见问题解决
    在Windows系统中安装TensorFlow GPU版是许多深度学习初学者面临的挑战。本文详细介绍了安装过程中的每一个步骤,并针对常见的问题提供了有效的解决方案。通过本文的指导,读者可以顺利地完成安装并避免常见的陷阱。 ... [详细]
  • 在HTML布局中,即使将 `top: 0%` 和 `left: 0%` 设置为元素的定位属性,浏览器中仍然会出现空白填充。这个问题通常与默认的浏览器样式、盒模型或父元素的定位方式有关。为了消除这些空白,可以考虑重置浏览器的默认样式,确保父元素的定位方式正确,并检查是否有其他CSS规则影响了元素的位置。 ... [详细]
  • 通过将常用的外部命令集成到VSCode中,可以提高开发效率。本文介绍如何在VSCode中配置和使用自定义的外部命令,从而简化命令执行过程。 ... [详细]
  • 在 CentOS 6.4 上安装 QT5 并启动 Qt Creator 时,可能会遇到缺少 GLIBCXX_3.4.15 的问题。这是由于系统中的 libstdc++.so.6 版本过低。本文将详细介绍如何通过更新 GCC 版本来解决这一问题。 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 本文详细介绍了在 CentOS 7 系统中配置 fstab 文件以实现开机自动挂载 NFS 共享目录的方法,并解决了常见的配置失败问题。 ... [详细]
  • com.sun.javadoc.PackageDoc.exceptions()方法的使用及代码示例 ... [详细]
  • 解决Only fullscreen opaque activities can request orientation错误的方法
    本文介绍了在使用PictureSelectorLight第三方框架时遇到的Only fullscreen opaque activities can request orientation错误,并提供了一种有效的解决方案。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 基于Linux开源VOIP系统LinPhone[四]
    ****************************************************************************************** ... [详细]
author-avatar
手机用户2602881417
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有