TypeCodes

未经处理的异常:0xC0000005:读取/写入位置冲突——从去掉字符串所有空格说起

在c/c++中,有时会遇到0xC0000005: 读取/写入位置冲突的问题。明明编译器编译通过,但是在执行的时候就出现Segmentation fault(coredump)了。

该错误是由于内存访问出错引起的,最常见于指针的错误使用和数组越界等。下面是博主之前的一个经历——去掉一个字符串前后的所有空格。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
char * pcontent = "  abcdef  "; //待去掉前后空格的字符串(共10字节)
char * p = NULL;

/* 1去除后面的空格 */
p = pcontent + strlen( pcontent ) - 1;  //指针p指向字符串的末尾
while( *p == 0x20 )
{
    p--;
}
*(p+1) = 0x00;  //将字符串中‘f’后面的一位空格改成结束符号'\0'
printf( "Line=[%d], pcontent=[%s]\n", __LINE__, pcontent );

咋一看,思路挺对的,遍历字符串后面的所有空格,然后只要将字符串中‘f’后面的一位空格改成字符串结束符即可。遗憾的是出现了Segmentation fault(coredump),用Vs调试,程序执行到断点 *(p+1) = 0x00; 时,出现未经处理的异常: 0xC0000005 写入冲突。

未经处理的异常: 0xC0000005 写入冲突

调用内存和堆栈可以看到字符串的地址是0x001b575c - 0x001b5765,其中 0x001b5764 里面的元素是 0x20,表示空格。

vs调用堆栈查看未经处理的异常: 0xC0000005 写入冲突

为什么把字符串结束符号'\0'写入到地址 0x001b5764 中就出错呢?原因是:定义指针pcontent的时候,语句char * pcontent = " abcdef "中的字符串是一个常量abcdef。常量在内存中是不可以被改写的,所以执行*(p+1) = 0x00;就会出现未经处理的异常: 0xC0000005: 写入位置冲突

另外,对于内存中的 0x00000000 地址,不能执行读取和写入操作。例如前面的char * p = NULL;这种指针初始化(避免成为野指针)操作,在后面不能直接来一个printf("%c", *p),否则就会出现错误未经处理的异常:0xC0000005:读取位置0x00000000时发生冲突

知道原理后,改成正确的去掉一个字符串前后的所有空格的程序:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * @FileName :  trimallspace.c
 * @Author   :  vfhky https://typecodes.com 20140725
 * @Functions:  去掉字符串前后所有的空格
*/
#include <string.h>
#include <stdio.h>
int main()
{
    char * p = NULL;
    char ccontent[20] = "  abcdef  ";   //把字符串放进一个数组而不是成为常量
    printf( "Line=[%d], ccontent=[%s]\n", __LINE__, ccontent );

    /* 1去除后面的空格 */
    p = ccontent + strlen( ccontent ) - 1;
    while( *p == 0x20 )
    {
        p--;
    }
    *(p+1) = 0x00;
    printf( "Line=[%d], pcontent=[%s]\n", __LINE__, p );

    /* 2去除前面的空格 */
    p = ccontent;   //重置指针变量p的位置
    while( *p == 0x20 )
    {
        p++;
    }
    printf( "Line=[%d], p=[%s]\n", __LINE__, p );
    return 0;
}
打赏支持

Comments »