📄 isemem.cpp
字号:
/********************************************************************
isemem.cpp
----------------------------------------------------------------
软件许可证 - 公有域软件
版权所有 (C) 2001 VCHelp coPathway ISee workgroup.
----------------------------------------------------------------
本文件用途: 内存防护系统实现文件
本文件编写人:
YZ yzfree##yeah.net
本文件版本: 20501
最后修改于: 2002-5-1
注:以上E-Mail地址中的##请用@替换。
----------------------------------------------------------------
修正历史:
2002-5 第一个测试版
********************************************************************/
/* 如果你的项目没有使用VC的预编译设置,可以将stdafx.h行注释掉 */
#include "StdAfx.h"
/* 如果用于 C 语言,并且不使用预编译选项,可打开下面的编译设置
#if defined(WIN32)
#include <windows.h>
#endif
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if defined(_MSC_VER)
#include <malloc.h>
#else
#include <mem.h>
#endif
#include "isemem.h"
/* 如果你想将本系统用于其它语言,可将其编译为DLL。
#ifdef WIN32
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
#endif
*/
#ifdef _DEBUG
static LPISE_MBINFO ise_memblock_header = (LPISE_MBINFO)0; /* 内存信息块链表头指针 */
static LPISE_MBINFO ise_memblock_tail = (LPISE_MBINFO)0; /* 内存信息块链表尾指针 */
static unsigned long ise_memblock_count = 0; /* 受防护内存块的个数 */
static CRITICAL_SECTION ise_mbheader_access; /* 内存信息块链表访问关键段 */
static char ise_err_buf[1024];
#ifdef WIN32
static HANDLE ise_heap; /* 内存信息私有堆 */
#else
#endif
/* 内部用函数 */
static LPISE_MBINFO CALLAGREEMENT _create_mb_header(void);
static void CALLAGREEMENT _free_mb_header(LPISE_MBINFO);
static void CALLAGREEMENT _insert_mb_header(LPISE_MBINFO);
static void CALLAGREEMENT _moved_mb_header(LPISE_MBINFO);
static LPISE_MBINFO CALLAGREEMENT _find_mb_header(void *);
/********************************************************************
* 内存防护系统接口函数
********************************************************************/
/* 打开内存管理子系统 */
ISEMEM_API void CALLAGREEMENT ise_open_mem_sys(void)
{
/* 此函数只能在程序运行时调用一次 */
assert(ise_memblock_count == 0);
assert(ise_memblock_header == 0);
assert(ise_memblock_tail == 0);
_create_heap();
InitializeCriticalSection(&ise_mbheader_access);
}
static char *ise_err0_str = "@@@>>> 警告:程序申请的内存块没有全部被释放!\n";
static char *ise_err1_str = "@@@>>> 文件 %s 中第 %d 行代码分配的内存块(长度为%d字节)没有被正确释放!\n";
/* 关闭内存管理子系统,并对管理情况做彻底检查 */
ISEMEM_API int CALLAGREEMENT ise_close_mem_sys(void)
{
int i, mark = 0;
EnterCriticalSection(&ise_mbheader_access);
if (ise_memblock_count)
{
mark = (int)ise_memblock_count;
ISE_PUTERR_STR(ise_err0_str);
inform_me(INFORM_LEVEL);
for (i=0; i<mark; i++)
{
assert(ise_memblock_header);
sprintf(ise_err_buf, ise_err1_str, ise_memblock_header->filename, ise_memblock_header->linenum, ise_memblock_header->use_len);
ISE_PUTERR_STR(ise_err_buf);
_ise_free(ise_memblock_header->pstart);
}
}
assert(ise_memblock_header == 0);
assert(ise_memblock_tail == 0);
assert(ise_memblock_count == 0);
LeaveCriticalSection(&ise_mbheader_access);
/* 销毁访问关键段 */
DeleteCriticalSection(&ise_mbheader_access);
/* 销毁私有堆 */
_destroy_heap();
return mark;
/* 0 - 内存管理正常,未发现任何问题 */
/* 非0 - 出现了未被正确释放的内存 */
}
static char *ise_err2_str = "@@@>>> 错误:内存防护系统的内部信息已被程序销毁,程序无法继续运行!\n";
static char *ise_err3_str = "@@@>>> 错误:操作系统异常,程序无法正常运行,建议重启计算机!\n";
static char *ise_err4_str = "@@@>>> 文件 %s 中第 %d 行代码分配的内存块(长度为%d字节)发生了写越界!\n";
static char *ise_err5_str = "@@@>>> 文件 %s 中第 %d 行代码分配的内存块(长度为%d字节)被覆写!\n";
static char *ise_err10_str = "@@@>>> 警告:文件 %s 中第 %d 行代码分配的内存块(%d字节)被程序用非法字符覆盖了,请检查一下各指针变量是否工作正常,或写内存操作是否越界。\n";
static char *ise_err11_str = "@@@>>> 警告:文件 %s 中第 %d 行代码分配的内存块(%d字节)的前端被非法数据覆盖,请检查一下前面的内存操作是否正常(有可能是无效的指针参与了运算)。\n";
static char *ise_err12_str = "@@@>>> 警告:代码在向文件 %s 中第 %d 行代码分配的内存块(%d字节)中写入数据时超出了该块的范围,请检查对该内存块的写入操作代码。\n";
/* 检测内存防护系统中所有的内存块是否存在错误(如果存在错误,则通知程序员)*/
ISEMEM_API void CALLAGREEMENT ise_check_mem_sys(void)
{
LPISE_MBINFO ptmp;
unsigned long mark;
EnterCriticalSection(&ise_mbheader_access);
/* 检测所有的受防护内存块 */
for (ptmp=ise_memblock_tail, mark = 0; ptmp != 0; ptmp = ptmp->prev, mark = 0)
{
/* 先检测防护系统自身是否正常 */
if ((ptmp->tag0 != ISE_MEMBLOCK_MARK)||(ptmp->tag1 != ISE_MEMBLOCK_MARK))
{
ISE_PUTERR_STR(ise_err2_str);
inform_me(INFORM_LEVEL);
}
/* 检测受防护内存的前后防覆写标志 */
if (((unsigned long *)(unsigned char *)(ptmp->pbegin+4+ptmp->use_len))[0] != ISE_MEMBLOCK_MARK)
{
mark |= 0x1;
}
if (((unsigned long *)ptmp->pbegin)[0] != ISE_MEMBLOCK_MARK)
{
mark |= 0x2;
}
/* 通知程序员有关的信息 */
switch (mark)
{
case 0: /* 未发现问题 */
break;
case 1: /* 本内存块写溢出 */
sprintf(ise_err_buf, ise_err12_str, ptmp->filename, ptmp->linenum, ptmp->use_len);
ISE_PUTERR_STR(ise_err_buf);
inform_me(INFORM_LEVEL);
break;
case 2: /* 前内存块写溢出 */
sprintf(ise_err_buf, ise_err11_str, ptmp->filename, ptmp->linenum, ptmp->use_len);
ISE_PUTERR_STR(ise_err_buf);
inform_me(INFORM_LEVEL);
break;
case 3: /* 全覆盖 */
sprintf(ise_err_buf, ise_err10_str, ptmp->filename, ptmp->linenum, ptmp->use_len);
ISE_PUTERR_STR(ise_err_buf);
inform_me(INFORM_LEVEL);
break;
default: /* 系统错误 */
ISE_PUTERR_STR(ise_err3_str);
inform_me(INFORM_LEVEL);
break;
}
}
LeaveCriticalSection(&ise_mbheader_access);
}
static char *ise_info0_str = "对不起,你给出的地址不在防护范围之内,这块内存可能是由其他内存分配函数分配的。\n";
static char *ise_info1_str = "这个地址所在的内存是由 %s 文件中的第 %d 行代码分配的,尺寸是 %d 字节,";
static char *ise_info2_str = "不过这个内存块现在已被破坏了,建议检查附近的内存写操作。";
static char *ise_info3_str = "这个内存块现在工作正常。";
/* 输出指定指针所在内存块的信息 */
ISEMEM_API void CALLAGREEMENT ise_put_pointer_info(void *p, char *info_buf)
{
LPISE_MBINFO pmb = 0;
assert(p&&info_buf);
EnterCriticalSection(&ise_mbheader_access);
/* 查找对应的信息块 */
pmb = _find_mb_header(p);
if (pmb == 0)
{
strcpy(info_buf, (const char *)ise_info0_str);
}
else
{
/* 输出相关内存块的信息 */
sprintf(info_buf, (const char *)ise_info1_str, pmb->filename, pmb->linenum, pmb->use_len);
/* 并检查改内存块是否正常 */
if ((((unsigned long *)(unsigned char *)(pmb->pbegin+4+pmb->use_len))[0] != ISE_MEMBLOCK_MARK)||\
(((unsigned long *)pmb->pbegin)[0] != ISE_MEMBLOCK_MARK))
{
strcat(info_buf, (const char *)ise_info2_str);
}
else
{
strcat(info_buf, (const char *)ise_info3_str);
}
}
LeaveCriticalSection(&ise_mbheader_access);
}
static char *ise_err20_str = "@@@>>> 警告:文件 %s 中第 %d 行代码所作的有效空间检测发现异常情况,指定的地址(%s 中第 %d 行代码分配的内存块,共 %d 字节)后面只有 %d 字节可用,而程序可能需要写入 %d 字节的数据,如果继续运行程序就有可能覆盖系统信息。请核查此处的内存操作代码。\n";
static char *ise_err21_str = "@@@>>> 警告:文件 %s 中第 %d 行代码中指定的地址不在防护范围之内,请核查。\n";
/* 确保指定地址p后面有size字节的有效空间可用(此函数与断言的作用相同)*/
ISEMEM_API void CALLAGREEMENT _ise_help_me_sure(void *p, int size, char *fn, int line)
{
LPISE_MBINFO pmb = 0;
assert(p&&size);
EnterCriticalSection(&ise_mbheader_access);
/* 查找对应的信息块 */
pmb = _find_mb_header(p);
if (pmb == 0)
{
sprintf(ise_err_buf, (const char *)ise_err21_str, fn, line);
ISE_PUTERR_STR(ise_err_buf);
inform_me(INFORM_LEVEL); /* 指定的地址不在防护范围内 */
}
else
{
unsigned char *pb = (unsigned char *)p;
/* 判断是否有足够的空间 */
if ((pb+size) > (pmb->pstart+pmb->use_len))
{
sprintf(ise_err_buf, (const char *)ise_err20_str, fn, line, pmb->filename, pmb->linenum, pmb->use_len, ((pmb->pstart+pmb->use_len)-pb), size);
ISE_PUTERR_STR(ise_err_buf);
inform_me(INFORM_LEVEL); /* 在指定的内存块中没有足够的空间来容纳size字节的数据 */
}
/* 顺便检查一下这块内存是否正常 */
if ((((unsigned long *)(unsigned char *)(pmb->pbegin+4+pmb->use_len))[0] != ISE_MEMBLOCK_MARK)||\
(((unsigned long *)pmb->pbegin)[0] != ISE_MEMBLOCK_MARK))
{
sprintf(ise_err_buf, (const char *)ise_info1_str, pmb->filename, pmb->linenum, pmb->use_len);
strcat(ise_err_buf, (const char *)ise_info2_str);
ISE_PUTERR_STR(ise_err_buf);
inform_me(INFORM_LEVEL);
}
}
LeaveCriticalSection(&ise_mbheader_access);
}
static char *ise_err30_str = "@@@>>> 注意:文件 %s 中第 %d 行代码中指定的地址不在防护范围之内,最好不要在这个地址上写入任何数据。\n";
/* 检测指定地址所在的内存块是否正常 */
ISEMEM_API void CALLAGREEMENT _ise_check_pointer(void *p, char *fn, int line)
{
LPISE_MBINFO pmb = 0;
assert(p);
EnterCriticalSection(&ise_mbheader_access);
/* 查找对应的信息块 */
pmb = _find_mb_header(p);
if (pmb == 0)
{
sprintf(ise_err_buf, (const char *)ise_err30_str, fn, line);
/* 指定的地址不在防护范围内 */
ISE_PUTERR_STR(ise_err_buf);
}
else
{
/* 检查内存块是否正常 */
if ((((unsigned long *)(unsigned char *)(pmb->pbegin+4+pmb->use_len))[0] != ISE_MEMBLOCK_MARK)||\
(((unsigned long *)pmb->pbegin)[0] != ISE_MEMBLOCK_MARK))
{
sprintf(ise_err_buf, (const char *)ise_info1_str, pmb->filename, pmb->linenum, pmb->use_len);
strcat(ise_err_buf, (const char *)ise_info2_str);
ISE_PUTERR_STR(ise_err_buf);
inform_me(INFORM_LEVEL);
}
}
LeaveCriticalSection(&ise_mbheader_access);
}
/* 分配一块受防护的内存块 */
ISEMEM_API void * CALLAGREEMENT _ise_malloc(long size, const char *fn, int linenum)
{
unsigned char *pb = 0;
LPISE_MBINFO pbm = 0;
assert(size);
EnterCriticalSection(&ise_mbheader_access);
/* 分配用户内存,+8为头、尾标志所占字节 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -