没有躲过的坑--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;}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

上面的程序在运行的时候就会报错,调试分析:

因为指针变量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);   //正确
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可以把语句 p1 = “abcd”; 改成 p1 = p3;,然后直接使用 strcat( p1, p2 );,这样是合法的。

博客C++“读取位置 0x****** 时发生访问冲突”的可能原因
有指出了一种情况:

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。导致产生“野指针”。

程序中的对象调用关系过于复杂,实在难以搞清楚某个对象究竟是否已经释放了内存,此时应该重新设计数据结构,从根本上解决对象管理的混乱局面。

不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow

您可能感兴趣的与本文相关的镜像

Yolo-v8.3

Yolo-v8.3

Yolo

YOLO(You Only Look Once)是一种流行的物体检测和图像分割模型,由华盛顿大学的Joseph Redmon 和Ali Farhadi 开发。 YOLO 于2015 年推出,因其高速和高精度而广受欢迎

### 空指针异常 0xC0000005 访问冲突 读取位置 0x00000000解决方案 空指针异常 `0xC0000005` 是 Windows 系统下常见的错误,通常表示程序试图访问无效的内存地址。当发生访问冲突读取位置为 `0x00000000` ,这通常意味着程序尝试解引用一个未初始化或已被释放的指针[^1]。 #### 原因分析 1. **未初始化的指针**:如果指针在使用前未被正确初始化,它可能指向无效的内存地址,例如 `0x00000000`。 2. **已释放的指针**:如果指针指向的内存已被释放,但程序仍然尝试访问该内存,就会导致访问冲突。 3. **数组越界**:访问数组超出其分配的范围也可能引发此类错误。 4. **信号与槽机制中的空指针**:在某些框架(如 Qt)中,如果信号触发传递了空指针,并且接收方尝试操作该指针,则可能导致此问题[^4]。 #### 解决方案 以下是针对上述原因的具体修复方法: 1. **检查指针是否为空**: 在使用指针之前,应始终验证其是否为非空。例如,在 C++ 中可以这样做: ```cpp if (pointer != nullptr) { // 安全地使用指针 } else { // 处理空指针情况 } ``` 2. **确保指针正确初始化**: 在声明指针,应明确初始化为 `nullptr` 或有效的内存地址。例如: ```cpp MyClass* obj = nullptr; // 初始化为 nullptr obj = new MyClass(); // 分配有效内存 ``` 3. **避免使用已释放的指针**: 如果指针指向的内存已被释放,应将其重新设置为 `nullptr`,以防止后续误用。例如: ```cpp delete pointer; pointer = nullptr; ``` 4. **处理数组越界问题**: 在操作数组,确保索引在合法范围内。例如: ```cpp int array[10]; for (int i = 0; i < 10; ++i) { array[i] = i; // 确保索引不超过数组大小 } ``` 5. **检查信号与槽机制**: 在使用信号与槽,确保传递的参数不是空指针。例如,在 Qt 中可以这样处理: ```cpp QObject::connect(listWidget, &QListWidget::currentItemChanged, this, [=](QListWidgetItem* item) { if (item != nullptr) { // 安全地操作 item } }); ``` #### 示例代码 以下是一个完整的示例,展示如何安全地处理指针和数组: ```cpp #include <iostream> using namespace std; class Example { public: void print() { cout << "Example class method" << endl; } }; void safePointerUsage(Example* ptr) { if (ptr != nullptr) { ptr->print(); // 安全调用 } else { cout << "Pointer is null!" << endl; } } int main() { Example* example = nullptr; // 初始化为 nullptr safePointerUsage(example); // 检查并处理空指针 example = new Example(); // 分配有效内存 safePointerUsage(example); // 正常调用 delete example; // 释放内存 example = nullptr; // 避免悬空指针 int array[5] = {1, 2, 3, 4, 5}; for (int i = 0; i < 5; ++i) { cout << array[i] << " "; // 确保索引在范围内 } return 0; } ``` ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值