在memcpy函数中,如果源地址指向的地址不可用(指向了一个错误的地址),memcpy函数肯定会报错直到死机。有什么办法在memcpy函数中检测源地址是否是正确的?或者,如何保证memcpy函数不会死掉?再或者,有没有什么其他方法,实现在内存复制前,能够发现这个内存复制操作有可能会导致程序DIE
解决方案 »
- 要用钩子才能100%确保WM_NCLBUTTONUP发送出去,并被钩子拦截?
- 我记得读书的时候是说中 国面积为全世界第三大.... 但是现在???
- 如何取别的机器MAC地址?SendArp跟哪些系统服务相关?
- 求助,如何不用Invalidate擦除背景!
- SkinMagic中库的冲突问题;
- 请大家进来帮我分析分析~!
- 求高手指点
- 有网络高手,能不能列出一些重要的协议所使用的端口,例如,HTTP 80,TCP 23,FTP 21等等。
- RUNTIME_CLASS意指??
- 各位在线老大,那里有类似资源管理器的源代码?如果有过类似开发经验,不妨谈一谈,让其他兄弟也从中获益.
- 遇到一个棘手问题
- [ListCtrl]我InsertColumn时,设成居中,为什么第一列还是靠左啊?
memcpy可能出现你说的那个错误,那么要用assert等函数确保原地址的正确
你可以参考memcpy溢出原理的文章,来分析自己的程序
记录申请信息类似检测泄露程序
memcpy的时候还要判断是否越界
其实最主要的是良好的编码习惯
3. 坏指针,越界和指针的强制转换
坏指针,越界和指针的强制转换往往是混在一起产生的。如果一个指针的内存结构被破坏了(被其他的代码以非正常的手段写过),那这个指针就被称为坏指针。坏指针的产生情况非常复杂,主要有:操作没有初始化的指针,越界操作内存,代码逻辑上的错误,指针强制转换越界。由于这几项的关连性太强,所以将其作为一个整体来说明:
在使用memcpy, strcpy之类的函数的之前,最好作一个被Copy对象的内存越界检查以确保内存Copy操作不会引起越界问题。比如 memcpy(lpTarget,lpSource,size_t) 就要做三个检查:首先检查lpTarget是否合法,是不是为NULL,有没有指向其他内存区域;其次要看lpSource是否合法;最后检查lpSource可操作内存的长度是否小于Size_t,lpTarget的内存长度是否小于Size_t。这三个检查一个都不能忽略。虽然不见得一定要在代码中做检查,但是使用的时候心里要有数,不能没有搞清楚就去使用。一旦出现内存操作越界的问题,那这个程序就会当掉。比如Cstring类的内部保存字符串指针的地址是一直在变化的,这个时候要小心操作,不要直接使用那个一直在变化的指针。
现在很多代码中都有强制转换指针类型的操作,比如LPBYTE转换成LPVOID。特别是在函数传参数的时候,经常需要做转换,但是那个转换是什么意思,一定要明白。比如转换指针类型之后,操作的内存空间是否会变化。 这个关键是基本数据类型是否熟悉的问题。 比如把一个LPBYTE指针转换成一个 char*,没有问题,两个的长度是相同的,都是一个byte。但如果把LPBYTE转换成一个 LPCTSTR,因为根据编码方式的不同,ANSI或者Unicode LPCTSTR的长度有时候是1个byte,有时候是2个byte。
定义一个BYTE数组来保存一些个字符。那定义数组的Code要这样写:
Temp = new BYTE[20*sizeof(TCHAR)];
不然的话,有可能会出错。 对于一些专门操作string(以NULL结尾)的函数,比如 lstrlen,如果其操作对象是非String那么,依然有可能出错。实际上,最好是Code需要什么样的类型的指针就定义什么样类型的指针。这样就能减少很多的错误。
自定义的函数中如果需要传入一个数组指针,比如上面的Temp指针,只要不是基本数据类型的话,传入指针的同时一定要把数组的长度传入。只是评一个指针类型,是很难判断指针的buffer是多大的,除了string类型的指针。传入指针的buffer的长度在需要把这个指针作为返回值的时候是比较有用的,这样在函数里面做内存Copy,准备返回的时候,就能判断内存Copy是否会产生越界现象。另外如果传入一个指针,但是不准备回写,那请你把这个指针定义为const类型,这样在编译的时候就能知道有没有在写这个指针的内存buffer。注意这个只是一种减少出错的办法,但是不是完美的。毕竟在运行期,代码实际上可以操作任何内存空间的。==============================================不过,记得有个函数检查指针合法性的...记不起来了
通常,如果是在进行内存复制时,源地址是不可用的,在调试时,程序会中断在memcpy.asm中的下面一句
rep movsd ;N - move all of our dwords
为了避免这种情况的出现,可以使用下面的方法:
__try
{
//访问内存地址0x000006
memcpy(pbDup, (char*)0x000006,1000); }
__except(EXCEPTION_EXECUTE_HANDLER)
{
AfxMessageBox("内存复制出错了");
}
// Includes all CMemoryState functions
CMemoryState msOld, msNew, msDif;
msOld.Checkpoint();
CAge* page1 = new CAge( 21 );
CAge* page2 = new CAge( 22 );
msOld.DumpAllObjectsSince();
msNew.Checkpoint();
msDif.Difference( msOld, msNew );
msDif.DumpStatistics();