生死疆界(上)--- 在new与delete之间,生死疆界(上)--- 在new与delete之间
【 tulaoshi.com - C语言心得技巧 】
生死疆界(上)--- 在new与delete之间
作者:土豆
void main(){ char *p = new char; cin>>p; cout<<p[2]; delete p;}在以上代码中,如果你输入:abcd,那么如你所望,你会看到"正确"的输出"c"。但是会有错误提示出现:
void(){char *p = new char;cin>>p;cout<<p;delete p;}如果只输入一个字符a,那么依然报错。是不是奇怪,分配了一个字符,输入了一个字符,那么错在哪里? 注意,最开始那行Debug Error!说明这是在Debug编译模式下才有的提示,如果你换到release频道,那么此提示不再出现,你成功得到了"c",仿佛程序一切正常。
void __cdecl operator delete(void *p) _THROW0(){ // free an allocated object free(p);}没有任何有用的信息,那就继续追进free(p)里。 不一会,我们追到了DBGHEAP.C中,你从文件名可以看出,这是在debug模式下才能进入的文件。
if (!CheckBytes(pbData(pHead) + pHead->nDataSize, _bNoMansLandFill, nNoMansLandSize)) _RPT3(_CRT_ERROR, "DAMAGE: after %hs block (#%d) at 0x%08X.n", szBlockUseName[_BLOCK_TYPE(pHead->nBlockUse)], pHead->lRequest, (BYTE *) pbData(pHead));前受阻。 是不是觉得这这模块巨可怕,呵呵,静下心来,很简单,因为有if存在,那么CheckBytes()一定是执行某种检验,如果检验失败,调用_RPT3()函数 在MSDN中,对_RPT函数族有这样的解释:
static int __cdecl CheckBytes(unsigned char * pb, unsigned char bCheck, size_t nSize){ int bOkay = TRUE; while (nSize--) { if (*pb++ != bCheck) { _RPT3(_CRT_WARN, "memory check error at 0x%08X = 0x%02X, should be 0x%02X.n", (BYTE *)(pb-1),*(pb-1), bCheck); bOkay = FALSE; } } return bOkay;}你看到了,这个函数只调用了_RPT3,再也没有其他的调用,看来,我们到头了。 下面是微软的程序员为这个函数写的注释的一部分:
*Purpose:* verify byte range set to proper value*Return:* TRUE - if all bytes in range equal bcheck* FALSE otherwise再明显不过了,这个函数检验一定范围的位是否设定为了正确的值(就是传进来的那么bCheck),如果正确,返回bOkay=TRUE,否则,返回bOkay=FALSE. 都挖完了,再也没有任何有用的信息,我们仍旧不知道微软是如何进行校验的,眼前依然一片黑暗。如果还有黎明的曙光,那么只能从传入的参数身上发出,呵呵,它们三肩负着我们的厚望啊。看看第一个参数unsigned char* pb。 if (*pb++ != bCheck)这条语句告诉我们要将pb所指内存地址的指与bCheck比较,那么我们还有最后一线希望:直接监视内存。
来源:http://www.tulaoshi.com/n/20160129/1485684.html
看过《生死疆界(上)--- 在new与delete之间》的人还看了以下文章 更多>>