今天在写代码时,发现莫名其妙的错误:

std::string strName = L“testtest”;

char* pOutString = new char(len + 1);
Decrypt((const char*)p, len, pOutString, len + 1);

...

delete pOutString;
pOutString = NULL;

运行到 delete时报错:Heap corruption detected ....

然后我把new 和delete改成数组形式,就一切正常了:

std::string strName = L“testtest”;
int nLen = strName.length();

char* pOutString = new char[len + 1];
Decrypt((const char*)p, len, pOutString, len + 1);

...

delete[] pOutString;
pOutString = NULL;

细想一下,原来是我大意了!!!

(1)

new char[10];分配一块连续的内存,也就是一个数组,里面有10个元素
new char(10);分配一块内存,有一个元素,该元素被初始化为10

char* ch = new char(10)  等效于 :

char* ch = new char;

*ch = 10;

(2)

而产生Heap corruption detected 错误的原因:

当输入超出了预分配的空间大小,就会覆盖该空间之后的一段存储区域,这就叫Heap Corruption。这通常也被用作黑客攻击的一种手段,因为如果在该空间之后的那段存储区域如果是比较重要的数据,就可以利用Heap Corruption来把这些数据修改掉了,后果当然可想而知了。

在VC里面,用release模式编译运行程序的时候,堆分配(Heap allocation)的时候调用的是malloc,如果你要分配10byte的空间,那么就会只分配10byte空间,而用debug模式的时候,堆分配调用的是_malloc_dbg,如果你只要分配10byte的空间,那么它会分配出除了你要的10byte之外,还要多出约36byte空间,用于存储一些薄记信息,debug堆分配出来之后就会按顺序连成一个链。

那么我们再来看看薄记信息中有些什么。还是上面10byte分配空间的例子,那么分配出的10byte空间的前面会有一个32byte的附加信息,存储的是一个_CrtMemBlockHeader结构,可以在DBGINT.H中找到该结构的定义:

typedef struct _CrtMemBlockHeader
{
// Pointer to the block allocated just before this one:
   struct _CrtMemBlockHeader *pBlockHeaderNext;
// Pointer to the block allocated just after this one:
   struct _CrtMemBlockHeader *pBlockHeaderPrev;
   char *szFileName;    // File name
   int nLine;                  // Line number
   size_t nDataSize;      // Size of user block
   int nBlockUse;         // Type of block
   long lRequest;          // Allocation number
// Buffer just before (lower than) the user's memory:
   unsigned char gap[nNoMansLandSize];
} _CrtMemBlockHeader;

/* In an actual memory block in the debug heap,
 * this structure is followed by:
 *   unsigned char data[nDataSize];
 *   unsigned char anotherGap[nNoMansLandSize];
 */

结构中的_CrtMemBlockHeader结构两个指针就不用解释是干嘛的了,szFileName是存储的发起分配操作的那行代码所在的文件的路径和名称,而nLine则是行号。nDataSize是请求分配的大小,我们的例子里当然就是10了,nBlockUse是类型,而lRequest是请求号。最后一项gap,又称NoMansLand,是4byte(nNoMansLandSize=4)大小的一段区域,注意看最后几行注释就明白了,在这个结构后面跟的是用户真正需要的10byte数据区域,而其后还跟了一个4byte的Gap,那么也就是说用户申请分配的区域是被一个头结构,和一个4byte的gap包起来的。在释放这10byte空间的时候,会检查这些信息。Gap被分配之后会被以0xFD填充。检查中如果gap中的值变化了,就会以Assert fail的方式报错。不过vc6中提示的比较难懂,DAMAGE :after Normal block(#dd) at 0xhhhhhhhh,而vs2005里面会提示Heap Corruption Detected!而如果你是release版本,那么这个错误就会潜伏直到它的破坏力发生作用。也许其后的区域存储着一个除数,而你的heap corruption把它改写成了0,那么会怎么样呢? :P
        至于其他的C/C++编译器中是否会有这样的机制,我就不是很清楚了,或许知道的朋友可以给我做些补充。

下面是我的见解:

我的出错程序:

unsigned int tLength=strlen(inSrcString);

char* tString=new char[tLength];     //注意这里!!!分配的数组大小应为tLength+1,因为最后还有一个'/0'

...

strcpy(tString,inSrcString);            //也要小心!如果inSrcString的长度大于tString的长度,会越界,显然Bug!本例先取inSrcString长度

/*附上strcpy大概实现,想然你会明白我的意思。

char* strcpy(char* pDest,const char* pSrc)

{

assert(pDest!=NULL&&pSrc!=NULL);

char* addr=pDest;

while((*pDest++=*pSrc++)!='/0');

retrun addr;

*/

...

delete[] tString;                  //字符数组,所以用delete[],就是这里报错!!!

我想C++的字符串操作,我是说像我这么原始的,而不是string类,一定要千万小心!!!祝你好运!

VC++ 报错:Heap corruption detected的更多相关文章

  1. C语言错误: HEAP CORRUPTION DETECTED

    程序源代码: //写文件两种方式(文本文件和二进制文件) #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<std ...

  2. 内存溢出(heap corruption detected:)

    今天又遇到了上次出现的bug,然后百度了一下,想起来这是内存溢出的毛病,故记录下来! 出现的问题就是这样: heap corruption detected: after normal block(# ...

  3. heap corruption detected错误解决方法调试方法以及内存管理相关

    1.heap corruption detected http://vopit.blog.51cto.com/2400931/645980   heap corruption detected:aft ...

  4. HEAP CORRUPTION DETECTED:after Normal block错误方法解决

    一:问题描述: 出现的问题如下: 二:问题产生的原因说明 该问题发生于操作堆内存的时候.产生该问题的原因是:你实际使用的内存大小超出了你实际申请的内存大小,在释放内存的时候就会发生该问题. 举个例子: ...

  5. heap corruption detected VS2015 C语言 报错

    申请动态内存时,申请的单元数为n,可用下标为0~n-1 但实际使用时超过了该范围,就会报这个错

  6. HEAP CORRUPTION DETECTED :after Normal block 错误

    http://blog.csdn.net/zhccl/article/details/7889590

  7. HEAP CORRUPTION DETECTED

    发生主要是由于这个问题给写入超出预分配的空间,注意检查越界情况 版权声明:本文博客原创文章,博客,未经同意,不得转载.

  8. 踩坑之VC报错 error RC2104 : undefined keyword or key name

    .RC文件中第541行 MENUITEM "CNDev,                       ID_CNDEV 少了一个"    正确的应该是MENUITEM " ...

  9. Vue报错 Duplicate keys detected: '1'. This may cause an update error. vue报错

    情况一.错误信息展示为关键字‘keys‘,此时应该检查for循环中的key,循环的key值不为唯一性 (很普通) 情况二.有两个相同的for循环,而这两个for循环的key值是一样的,此时将一个的ke ...

随机推荐

  1. awk之match函数

    功能:match函数是用于个性化定制搜索模式. 例子: 文件内容: this is wang ,not wan that is chen, not che this is chen ,and wang ...

  2. iotop监控磁盘动态安装

    开始装iotp tar xvf iotop-0.3.1.tar.gz 用python安装(如果没有蟒蛇, yum一个吧) cd iotop-0.3.1 python setup.py build py ...

  3. 20145317彭垚《网络对抗》Exp9 Web安全基础实践

    20145317彭垚<网络对抗>Exp9 Web安全基础实践 基础问题回答 SQL注入攻击原理,如何防御? SQL注入攻击就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询 ...

  4. 20145324王嘉澜《网络对抗技术》web安全基础实践

    实验内容 •使用webgoat进行XSS攻击.CSRF攻击.SQL注入 实验问答 •SQL注入攻击原理,如何防御 ①SQL注入攻击是攻击者在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL ...

  5. 20165310 Java实验四 《Android程序设计》

    20165310 实验四 <Android程序设计> 第24章:初识Android 任务一:改写res目录中的内容,Hello World后要显示自己的学号,自己学号前后一名同学的学号 首 ...

  6. Easyui 官网网址

    http://www.jeasyui.com/download/list.php 下载版本1.5.2的easyui中文API,可在CSDN网站http://download.csdn.net/down ...

  7. 【第六章】 springboot + 事务

    在实际开发中,其实很少会用到事务,一般情况下事务用的比较多的是在金钱计算方面. mybatis与spring集成后,其事务该怎么做?其实很简单,直接在上一节代码的基础上在相应的方法(通常是servic ...

  8. Intellij新建Spring项目引入用户目录下的Spring jar包

    首先,在IntelliJ IDEA中新建module,选择Spring应用:   在初次使用时,如果IDE检测到本地没有spring核心库,则会在新建过程中下载对应库文件,在使用spring框架时,可 ...

  9. [Pytorch]Pytorch中图像的基本操作(TenCrop)

    转自:https://www.jianshu.com/p/73686691cf13 下面是几种常写的方式 第一种方式 normalize = transforms.Normalize([0.485, ...

  10. Goroutines和Channels(四)

    如果说goroutine是Go语言程序的并发体的话,那么channels则是它们之间的通信机制. 一个channel是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值 ...