编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结

0xC0000005异常

  • 一,对空指针的访问
  • 二,对只读空间的修改
  • 三,动态内存二次free/delete
    • (Ⅰ)自己程序的二次delete
    • (Ⅱ)对堆内存的二次delete
  • 四,free/delete了非动态内存
  • 五,数组越界修改(打印可能不会异常)
  • 六,修改不属于自己的内存空间
    • ①修改不属于自己的内存空间,因为其右值未被初始化,指向未知内存**
    • ②数组越界修改也是属于这种类型的异常**
    • ③指针的越界读取访问也会导致异常
  • 七,因为编译器实现不同而导致的异常崩溃
  • 八,总结
  • 最后:觉得有用的请点赞关注一波,别只收藏不点赞呐,谢谢。

一,对空指针的访问

编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第1张图片
再贴多一种类似情况,对指针解引用后,操作不属于自己的内存空间(0地址),0地址是不准许
访问的!!!
编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第2张图片

二,对只读空间的修改

一种情况是这样的,对只读空间进行修改,也是不允许的,一改就会出错!!!直接崩溃编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第3张图片
另外一种就是使用了strcpy强行改变了常量字符串的内容
这种就比较隐蔽了。。。单步调试是一种神器

三,动态内存二次free/delete

(Ⅰ)自己程序的二次delete

我用C++写了链表类,然后将两个链表合并为1个,简单的将第2个链表的尾指针指向了第1个链表的头指针,然后
析构了第二个链表之后,又析构了第一个合并后的链表
,造成了非常隐蔽的double free,令我十分不解,
单步调试也发现不了问题,后来直接打印所有节点的地址,
恍然大悟!!!是二次free,简直了!!!
第一张图是有问题时的情况:
释放的内存地址0083E8A8被释放了2次,第一次释放是析构输出的第一行,第二次是析构输出的最后一行
编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第4张图片

第二张图解决了问题
编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第5张图片

(Ⅱ)对堆内存的二次delete

vs会直接异常,但是cb里面没有出现异常
编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第6张图片

四,free/delete了非动态内存

使用了非动态内存或者使用了不属于自己的内存空间
编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第7张图片
对上图的解释:你试图对随机的一个地址111进行delete,这个内存不属于你,可能不是动态内存,但是你却试图释放它,其结果是未知的,往往导致程序崩溃!!

五,数组越界修改(打印可能不会异常)

如果你仅仅是打印出来,可能不会异常,但是,如果你试图修改不属于你的内存空间,
就一定会异常!!
编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第8张图片

六,修改不属于自己的内存空间

①修改不属于自己的内存空间,因为其右值未被初始化,指向未知内存**

编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第9张图片
注:另外常见的还有strcpy,strncpy,strcat,memset等库函数,如果第一个参数未被初始化,
程序同样崩溃

上图的解决方案:对q进行初始化,让其指向有效的空间,这里我使用了new分配内存空间
,当然你改成char p[4];也是合理的;
图示如下:
编译器出现Process returned -1073741819 (0xC0000005)以及编译器的异常警告,Linux的段错误总结_第10张图片
还有一种情况就是如下

char* p;//指向未知内存
scanf("%s",p);//试图修改不属于自己的空间
printf("%s",p);//如果用Clion去debug,断点会一直停在scanf那一行,
               // 报告EXC_BAD_ACCESS!!!!

改正如下:

char* p = new char[100];//如果申请成功,指向有效内存
scanf("%s",p);//试图修改属于自己的空间
printf("%s",p);//ok!!

②数组越界修改也是属于这种类型的异常**

③指针的越界读取访问也会导致异常

#include
using namespace std;
class Stu{
private:
	char* name;
public:
	Stu(const char* _name):name(new char[(std::strlen(_name)+1]){
		//省略申请失败的检查
		std::strcpy(name,_name);
	}	
};
void write(Stu* s, int n) {
    ofstream out("C:\\Users\\axin\\Desktop\\b.txt", ios::out);
    for (int i = 0; i < n; i++)
        out.write(reinterpret_cast<char*>(s + i), sizeof(Stu));
        //这个write只是把name指向的首地址,即指针本身的值写进去了文件里面
        //但是会导致读取的时候出现字符串读取异常,所以read出来再cout对象的时候会
        //程序崩溃!!!!
}
void read(Stu* s, int n)
{
    ifstream in("C:\\Users\\axin\\Desktop\\b.txt", ios::in);
    for (int i = 0; i < n; i++)
    {
        in.read(reinterpret_cast<char*>(s + i), sizeof(Stu));
        if ((s+i)->getScore() >= 60) {
            cout << s[i];//间接访问对象的name,由于读取字符串异常,访问异常的指针
            //必然运行崩溃
        }
    }
}
int main()
{
	Stu s[3] = {
        Stu(20190001,"Li",99),
        Stu(20190002,"Zhang",59),
        Stu(20190003,"Zhao",100)
    };
    //write(s, 3);
    //如果事先把对象写入文件,后面只是调用read读取,那么访问对象name的时候就会导致
    //程序崩溃
    read(s, 3);
    return 0;
}

总结

这正是不能把含有string成员的对象写入文件的原因,string内部使用指针管理动态内存
我这个例子也是用动态内存管理,都会出现同样的问题!!!

七,因为编译器实现不同而导致的异常崩溃

Vs2019下:
有一次我写的函数忘记返回了vector,结果程序执行完最后一条代码后,异常崩溃,
后面发现编译器给了一个Warning:不是所有路径都有返回值,然后我写了个return后就
正常了

八,总结

哎,就是非法内存访问错误,各种内存管理和地址的非法访问

最后:觉得有用的请点赞关注一波,别只收藏不点赞呐,谢谢。

参考文章:
百度百科-段错误
作者:杰出天下的一篇文章:段错误

你可能感兴趣的:(c++语法错误,数据结构,指针,c++,链表,数据结构)