##没有躲过的坑--0xC0000005: 读取位置 xxx时发生访问冲突
Bjarne Stroustrup老爷子说过:
**“C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.”**
最近的工程时不时的出现0xC0000005: 读取位置 xxx时发生访问冲突,导致崩溃。
先看看下面的程序:
~~~
#include<iostream>
#include <string>
int main()
{
char * p1 = (char *)malloc(sizeof(char) * 20);
char p3[20] = "igkl";
char * p2 = "efgh";
p1 = "abcd"; //p1指向字符串"abcd"的首地址, 而不是把"abcd"拷贝到malloc开辟的内存块中
strcat(p1, p2); //报错: 0xC0000005异常,访问冲突
strcat(p3, p2); //正确
std::cout << p1 << std::endl;
std::cout << p2 << std::endl;
std::cout << p3 << std::endl;
std::cout << p2 << std::endl;
//释放内存
free(p1);
p1 = NULL;
return 0;
}
~~~
上面的程序在运行的时候就会报错,调试分析:
因为指针变量p1(0x00d7576c)所指向的字符串常量“abcd”后面,也即字符’d’的地址是 0x00d7576c+3=0x00d7576f 。而它后面以地址 0x00d75770 开始的内存块是不属于指针变量p1的,没有访问权限,所以把拷贝自指针变量p2(0x00d75774)指向的字符串“efgh”到以 0x00d75770 为起始地址的内存块中会报错。
如果这样修改:
~~~
char p3[20] = "igkl";
char * p1 = (char *)malloc(sizeof(char) * 20);
p1 = p3;
char * p2 = "efgh";
strcat(p1, p2); //正确
strcat(p3, p2); //正确
~~~
可以把语句 p1 = “abcd”; 改成 p1 = p3;,然后直接使用 strcat( p1, p2 );,这样是合法的。
博客[C++“读取位置 0x****** 时发生访问冲突”的可能原因](http://blog.csdn.net/pkueecser/article/details/6066850 "0xC0000005可能的错误")
有指出了一种情况:
malloc一个100内存的空间用于读入文件,当文件的大小超过100时,并且程序中再使用100之后的内存时,就会产生“0xC0000005: 读取位置 xxx时发生访问冲突”这样的错误。
还有可能产生的原因:
**申请的内存没有释放**
new后必须delete
malloc后必须free
创建内核对象(比如CreateFile,CreateMutex,CreateThread),后必须释放内核对象句柄.
创建内存映射文件,CreateFileMapping,MapViewOfFile后必须CloseHandle(),UnMapviewofFile
创建GDI对象后,比如LoadIcon,LoadImage,CreateImageList等等,必须Destroy掉
创建DC后,比如GetDC(), 必须释放DC句柄
保留虚拟地址空间 VirtualAlloc(),然后提交物理存储器后,必须释放掉
**出现死循环导致内存泄露**
**所有的第三方类库存在内存泄露相关的BUG**
常见的溢出主要有:
**内存分配未成功,却使用了它。**
常用解决办法是,在使用内存之前检查指针是否为NULL。如果指针p 是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。如果是用malloc 或new 来申请内存,应该用if(p==NULL)或if(p!=NULL)进行防错处理。
**内存分配虽然成功,但是尚未初始化就引用它。**
内存分配成功并且已经初始化,但操作越过了内存的边界。
例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for 循环语句中,循环次数很容易搞错,导致数组操作越界。
**使用free 或delete 释放了内存后,没有将指针设置为NULL。导致产生“野指针”。**
程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。
不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。
- 前言
- deprecated关键字
- 指针(内存泄露)
- 头文件相互包含(Compiler error C2653: not a class or namespace name)
- 获取一张图片的width和height
- This function or variable may be unsafe.
- 智能指针陷阱
- wstring与string的转换
- windows下chrome浏览器插件不能安装
- 重定义关键字
- 正确释放vector的内存
- 获取设备环境HDC
- 抽象类不能实例化对象(但是你明明定义的不是抽象类)
- 重载赋值运算符的自我赋值
- 程序中的变量未初始化
- 成对使用new和delete时要采取相同的形式
- 意想不到的除数为零
- map的初始化(插入数据)
- 正则表达式截取字符串
- 捕获窗口之外的鼠标消息(钩子还是??)
- 类中的静态成员变量(static or const static)
- 有if就要有else(一定成对)
- map查找结果处理
- 使用using namespace std的坏习惯
- new一个指针数组、以及创建动态二维数组
- 使用太多的全局变量
- 没有及时break出for循环
- vector使用erase后迭代器变成野指针
- C++函数的默认参数(重新定义默认参数)
- 0xC0000005: 读取位置 xxx时发生访问冲突
- std::string初始化、最快速判断字符串为空
- 你开发的软件安装在C盘Program Files (x86)下产生的异常