软件编程体会(为内存调试做准备)
作者:燕青 2007年4月24日内存调试是软件开发后期最繁重,最无聊,也最令人伤心的事情。既然作为软件开发环节中的不可缺少的一环,我们是否可以为它在开发前期做些有益的事情呢?嗯,…,可以,让我们探讨一下吧。
软件的内存问题,一般而言有两种。第一,内存泄露。第二,指针越界。这两个问题一直都困惑着很多的软件开发人员,这篇文章将着重探讨一下个人的解决方法。在C语言中,内存的分配函数主要有下面几个:
#include <stdlib.h>
void *calloc(size_t nmemb, size_t size); void *malloc(size_t size); void free(void *ptr); void *realloc(void *ptr, size_t size); |
如果我们在程序中直接使用它们,那么在日后的内存调试过程中可能会改动诸多的相关源文件,这个是我们不希望的情景。我的想法是使用我们的项目中自定义的宏来取代直接的使用。比如:
#if !defined( WYQ_DBG_MEM )
#include <stdlib.h>
#define WYQMalloc( size ) malloc( size ) #define WYQCalloc( nItem, itemSize ) calloc( nItem, itemSize ) #define WYQRealloc( ptr, size ) realloc( ptr, size ) #define WYQFree( ptr ) free( ptr )
#else #define WYQMalloc( size ) WYQMallocEx( (size), __FUNCTION__, __FILE__, __LINE__ ) #define WYQCalloc( nmemb, size ) WYQCallocEx( (nmemb), (size), __FUNCTION__, __FILE__, __LINE__ ) #define WYQRealloc( ptr, size ) WYQReallocEx( (ptr), (size), __FUNCTION__, __FILE__, __LINE__ ) #define WYQFree( ptr ) WYQFreeEx( (ptr), __FUNCTION__, __FILE__, __LINE__ ) void *WYQMallocEx( size_t size, const char *caller, const char *fileName, int lineNo ); void *WYQCallocEx( size_t nmemb, size_t size, const char *caller, const char *fileName, int lineNo ); void *WYQReallocEx( void *ptr, size_t size, const char *caller, const char *fileName, int lineNo ); void WYQFreeEx( void *ptr, const char *caller, const char *fileName, int lineNo );
#endif |
在不进行内存调试的时候,我们WYQ_DBG_MEM不将被定义,我们就等同于直接使用ANSC C的内存函数,当WYQ_DBG_MEM被定义时,内存函数就换为调试内存函数,所有相关的内存监控等操作将在这些函数中得以实现。与先前唯一不同的是,仅仅在Makefile中加入了WYQ_DBG_MEM宏和相关的内存调试源代码。难道这样不是一个很好的前期准备吗?
或许有些读者觉得,有些内存的调试工具可以直接挂接在ANSC C的内存函数的,为什么还要使用这个蹩脚的宏来控制呢?你说的有一定道理,但是有些工具你必须修改相关的源文件,并且往往是线程不安全的,如果我们要使用这些工具,如何改动源代码?我想其中的工作量应该是很大的吧?!如果我们把所以得问题点都归结于自定义的这些内存调试函数,所有的问题都迎刃而解,对后期的工作量而言,确实帮助很大。你觉得呢?
小结
本篇主要探讨了一点对内存调试的一点点小的经验,可能有很多纰漏,也望读者见谅。如果能够给大家带来一些好的启迪,那么就是它的最大收获了。谢谢!