返回介绍

15.2 检测内存泄漏和其它错误

发布于 2025-03-08 15:27:55 字数 2866 浏览 0 评论 0 收藏 0

在理想状态下,当你的应用程序退出时,所有的对象都应该被你的应用程序或者 wxWidgets 本身释放,不会有残留的内存需要操作系统自己去释放.不用关心内存的释放听上去似乎非常的诱人,但是,我们还是要说,你应该自己控制所有对象的释放,而不要把它留给操作系统,因为通常,内存泄漏都是一些其它重大问题的前兆,它可能导致你的系统在一段时间内出现严重的内存问题.而当你已经转而关注程序的其它方面的时候,会过头来研究哪里出现了泄漏是一件非常令人沮丧的事情,因此,让你的程序尽量保持对内存泄漏的零容忍度不是一个坏事。

那么,怎样才可能让你的应用程序拥有这种检测内存泄漏的能力呢?各种各样的第三方工具提供了这种能力甚至更多其它的能力,而且, wxWidgets 也提供了一个自己的简单的内建的内存检测器.如果你想使用它,在 windows 平台上,你需要打开 setup.h 中的几个开关,而在 linux 平台上,configure 程序需要一些特殊的开关:

在 windows 平台上,你需要:

#define wxUSE_DEBUG_CONTEXT 1
#define wxUSE_MEMORY_TRACING 1
#define wxUSE_GLOBAL_MEMORY_OPERATORS 1
#define wxUSE_DEBUG_NEW_ALWAYS 1

而对于 configure 程序,需要传递这样的参数:

--enable-debug --enable-mem_tracing --enable-debug_cntxt

另外,使用这个系统还有一个限制:到作者停笔之前,它还不支持 MinGW 或 Cygwin 编译器,并且如果你的代码中使用了 STL 或者使用 CodeWarrior 编译器,你将不能使用 wxUSE_DEBUG_NEW_ALWAYS 选项。

如果打开了 wxUSEDEBUGNEWALWAYS 选项,那么所有使用 new 操作分配对象的地方都将被 new (_TFILE,__LINE) 代替,后者已经被重新使用调试版本的定制内存分配和释放机制进行实现.如果想不重新定义 new 而显式使用调试版本的 new 过程,你可以在使用 new 的地方用 WXDEBUG_NEW 代替。

最简单的使用这个系统的方法是:什么都不做,就只运行你的程序,作该做的事情,然后退出应用程序,然后检查是否有任何内存泄漏被报告.下面的内存泄漏报告的一个例子:

There were memory leaks.

- Memory dump -
.\memcheck.cpp(89): wxBrush at 0xBE44B8, size 12
..\..\src\msw\brush.cpp(233): non-object data at 0xBE55A8, size 44
.\memcheck.cpp(90): wxBitmap at 0xBE5088, size 12
..\..\src\msw\bitmap.cpp(524): non-object data at 0xBE6FB8, size 52
.\memcheck.cpp(93): non-object data at 0xBB8410, size 1000
.\memcheck.cpp(95): non-object data at 0xBE6F58, size 4
.\memcheck.cpp(98): non-object data at 0xBE6EF8, size 8

- Memory statistics -
1 objects of class wxBitmap, total size 12
5 objects of class nonobject, total size 1108
1 objects of class wxBrush, total size 12

Number of object items: 2
Number of non-object items: 5
Total allocated size: 1132

上面的例子显示有一个 wxBrush 对象和一个 wxBitmap 对象被分配了但是没有被释放,还有一些其它的未知的对象没有被释放,因为它们没有提供 wxWidgets 的运行期类型信息,因此无法确定对象的类型.在某些集成开发环境中,你可以通过双击报告行显示相应的代码中分配这个对象的位置,这通常是检查内存泄漏问题一个很好的开始.当然,为了最好的报告效果,最好给任何继承自 wxObject 都提供运行期类型信息,方法是,在类声明的部分增加 DECLARE_CLASS(class) 宏,在类实现的地方增加 IMPLEMENT_CLASS(class, parentClass) 宏。

这个内存检测系统还试图检测那些内存越界或重复释放的错误.在分配内存的时候,它自动在已经分配的内存块上设置一个"good"标记,在释放的时候将会检查这个标记,如果释放的内存块没有这个标记,则报告一个内存释放错误.这将帮助你发现那些隐藏的,也许在多次运行以后才会导致系统异常的内存错误。

wxDebugContext 类的一些静态函数也很有用处,你可以通过 PrintClasses 函数获取当前系统中分配的对象的列表, PrintStatistics 函数可以打印出当前系统中的已知类型对象和未知类型对象的个数.使用 SetCheckpoint 函数,你可以告诉 wxDebugContext 忽略这个函数调用以前的内存分配动作,而仅关注这以后的内存分配.详情请参考 samples/memcheck 例子或者 wxDebugContext 的相关手册。

除了 wxWidgets 内建的基本系统,你还可以使用别的商业的或者免费的内存检测软件,商业软件比如:BoundsChecker, Purify 或 AQtime 等.自由软件比如:StackWalker,ValGrind,Electric Fence 或来自 Fluid Studios 的 MMGR 等.如果你使用的是 Visual C++,wxWidgets 使用的是编译器内置的内存检测机制,它不会给出类的名字但是会给出行号.最好是打开 wxUSE_DEBUG_NEW_ALWAYS 选项,因为它将重定义 new 过程,除非打开这个选项导致别的第三方的库出现兼容方面的问题。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文