再谈“0xC0000005读取写入位置冲突”——正确使用指针访问内存

转自:http://www.typecodes.com/cseries/pointermemaccess0xC0000005.html

前面一篇文章中,总结了错误使用指针指向一个字符串常量,然后对该字符串常量进行写入操作导致出错:“未经处理的异常:0xC0000005: 读取/写入位置发生访问冲突”。这篇文章继续使用指针来探索这个问题。

1 测试程序:“异常: 0xC0000005: 写入位置 0xxxxxxxxx 时发生访问冲突”


下面是一个测试程序,主要是字符串的“连接”——strcat函数,malloc有迷惑性。其中,指针p1指向malloc在堆上开辟的连续内存块,数组p3是一种正确的字符连接方法。

/**
 * @FileName :  pointermemaccess0xC0000005.c
 * @Author   :  vfhky http://www.typecodes.com 2014.08.25 20:00
 * @Functions:  不正确使用指针p1导致出现“异常: 0xC0000005”和正确使用数组实现字符串的连接
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main( int argc, char * argv[] )
{
    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 );   //正确
    printf( "p1=[%s], p2=[%s]\n", p1, p2 );
    printf( "p3=[%s], p2=[%s]\n", p3, p2 );

    //释放内存
    free( p1 );
    p1 = NULL;
    return 0;
}
</pre><pre name="code" class="cpp"> 
<h3><span style="font-family: Arial, Helvetica, sans-serif;">2 在vs中设置断点并调试</span></h3>如下图设置好断点后,单步执行到第10行。此时指针变量p1的值是 0x008734c0 ,p2的值是 0x00d75774 ,数组p3的起始地址是 0x0036f928 。
<img src="https://img-blog.csdn.net/20141205215314511?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRmx5aW5nQmlyZF9TWEY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
2.1详细查看指针变量p1、p2以及数组p3的内存情况:(第10行)
此时,指针变量p1通过语句 char * p1 = (char *)malloc( sizeof(char)*20 ); 指向起始地址为 0x008734c0 到 地址 0x008734d3 的内存块(大小为 20 字节)。
<img src="https://img-blog.csdn.net/20141205215447003?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRmx5aW5nQmlyZF9TWEY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

指针变量 p2 通过执行 char * p2 = "efgh"; 指向起始地址为 0x00d75774 的字符串“efgh”(共占 4 字节)。
<img src="https://img-blog.csdn.net/20141205215550296?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRmx5aW5nQmlyZF9TWEY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">数组 p3 通过 char p3[20]= "igkl"; 开辟了起始地址为 0x0036f928 的内存块(共占 4 字节),存储字符串“igkl”。</span>
<img src="https://img-blog.csdn.net/20141205215631773?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRmx5aW5nQmlyZF9TWEY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

2.2继续单步调试并查看内存情况:(第11行)
上述变量初始化完毕后,单步执行到第 11 行的断点。这时指针变量p1由最初的指向 0x008734c0 变成指向字符串“abcd”的地址 0x00d7576c 。p2 的地址仍不变(0x00d75774),p3的地址也不变(0x0036f928)。
<img src="https://img-blog.csdn.net/20141205215813797?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvRmx5aW5nQmlyZF9TWEY=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />

详细查看指针变量p1的内存情况:起始地址是 0x00d7576c ,该内存块存储的字符串是“abcd”。


2.3继续单步调试并查看内存情况:(第12行)

然后,单步执行到第 12 行的断点,出现错误:test.exe 中的 0x0f85d2e9 (msvcr100d.dll) 处有未经处理的异常: 0xC0000005: 写入位置 0x00d75770 时发生访问冲突。也即在执行第11行的 strcat( p1, p2 ); 语句时,发生内存访问错误。该语句是把作为src的指针变量p2(0x00d75774)指向的内存块中的字符串“efgh”拷贝一份,然后复制到作为dst的指针变量p1(0x00d7576c)所指向内存块中的的字符串常量“abcd”后面。调用堆栈可以看到,当执行 msvcr100d.dll!strcat(unsigned char * dst, unsigned char * src) 对应的strcat.asm汇编文件中第178行语句 mov [edi], edx 时出错。



3 原因分析


其实,通过上面的单步调试,我们也已经知道原因了。现总结一下:因为指针变量p1(0x00d7576c)所指向的字符串常量“abcd”后面,也即字符'd'的地址是 0x00d7576c+3=0x00d7576f 。而它后面以地址 0x00d75770 开始的内存块是不属于指针变量p1的,没有访问权限,所以把拷贝自指针变量p2(0x00d75774)指向的字符串“efgh”到以 0x00d75770 为起始地址的内存块中会报错。可以把语句 p1 = "abcd"; 改成 p1 = p3;,然后直接使用 strcat( p1, p2 );,这样是合法的。


  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个异常通常是由于程序访问了一个无效的内存地址导致的。可能的原因包括: 1. 程序未正确初始化或释放指针,导致指针指向无效的内存地址。 2. 程序访问了已经释放的内存地址。 3. 程序访问了没有权限的内存地址。 4. 程序访问了超出数组边界的内存地址。 要解决这个问题,你需要对程序进行调试,查看程序在哪里出现了错误。可以使用调试器来跟踪程序的执行过程,并定位导致异常的代码行。另外,你也可以加入一些安全检查来避免这类问题的出现,例如在使用指针时,始终检查指针是否为空或是否已经释放等。 ### 回答2: 0x00007FF79C6F2570 处引发的异常是 0xC0000005,也被称为访问冲突异常。这个异常意味着程序在尝试读取内存位置 0xFFFFFFFFFFFFFFFF 时发生了错误。 这个异常通常是由以下原因之一引起的: 1. 空指针引用:程序尝试读取指针指向的内存地址,而空指针不指向任何有效的内存位置。 2. 使用未初始化的指针:程序使用未初始化的指针进行读取写入操作,导致访问到无效的内存位置。 3. 内存越界:程序访问了超出其分配内存范围的内存位置,导致冲突发生。 4. 内存访问冲突:程序并发访问了同一个内存位置,导致访问冲突。 要解决这个异常,我们可以采取以下方法之一: 1. 检查空指针引用:确保在使用指针之前,它已经指向了有效的内存地址。可以使用条件语句或空指针检查进行验证。 2. 初始化指针:在使用指针之前,始终将其初始化为有效的内存地址,可以使用NULL或nullptr进行初始化。 3. 细致检查内存分配:确保分配的内存范围足够大,以容纳程序读取写入的数据。 4. 同步访问:在多线程编程中,确保对共享内存位置访问是同步的,避免并发冲突。 最好的方法是通过调试器或日志来确定导致异常的具体原因,以便更好地解决问题。综上所述,0x00007FF79C6F2570 处引发的 0xC0000005 异常通常与内存访问冲突有关,需要检查指针引用、内存分配和并发访问等方面。 ### 回答3: 0x00007FF79C6F2570 处(位于 homework10.exe 中)引发的异常: 0xC0000005: 读取位置 0xFFFFFFFFFFFFFFFF 时发生访问冲突。 这个错误消息表示在程序运行时发生了一个异常。异常代码0xC0000005表示该异常是一个访问冲突异常,即内存访问错误。 异常的具体位置在0x00007FF79C6F2570,这个地址是指程序中的某个位置。由于我无法获取完整的程序代码,所以无法确定具体是什么引起了这个异常。 错误消息也提到了一个读取位置0xFFFFFFFFFFFFFFFF,这是一个特殊的内存地址,表示无效的内存位置。这表明代码在尝试读取一个无效的内存位置时引发了访问冲突异常。 要解决这个问题,我们可以尝试以下几个步骤: 1. 检查程序代码中与该地址相关的部分。可能存在指针或数组索引错误导致读取无效位置。 2. 检查程序是否正确申请和释放内存内存管理错误也可能导致访问冲突异常。 3. 确保所使用的库或依赖项是最新版本,避免已知的Bug。 4. 在程序中加入适当的异常处理机制,以便在发生异常时捕获并处理错误。 如果以上方法无法解决问题,可以尝试使用调试工具或记录程序执行过程中的相关日志,以便更详细地分析和定位异常的原因。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值