关于c++中的Debug以及runtime_error之segment_fault
差不多每次编一些竞赛类的程序都会至少给我报一次runtime_error(运行时错误)。这或许也是广大OIer心中永远的痛。~_~
本文主要讨论如何对runtime_error以及其中的segment_fault部分进行调试。本文以dev-c++5.11作为环境,由于以竞赛为主,本文不涉及指针、c++中的类等部分。
下面所有经验,均为本人在编程过程中所实际涉及并进行应用。
一、关于runtime_error(运行时错误)
运行时错误大概分为以下几类:
1、访问到不应访问的地址(如数组越界)
2、内存溢出(如数组过大)
3、算术上溢或下溢(如除以0)
4、段错误(各种其它错误)
除最后一种情况的一部分外,剩余错误发生时通常会在执行.exe文件时显示“已停止运行”。
(一)地址越界及溢出
通常情况下(不考虑指针地址非法)数组开过大会导致编译错误(Complie Error)。但是访问下标负数或数组过小会导致访问到数组以外的范围。
除将数组范围增大之外,通常情况下可以开一个新数组,当数组内存溢出时多余内容会流入新数组以避免错误发生(不推荐这种做法,无法确定内容剩余部分)。
(二)算术上溢及下溢
我们可以在每个可能出现错误的位置尝试c++中的try-throw-catch子句。
比如遇到除以0:
#include <iostream>
using std::cout;
using std::cin;
using std::cerr;
int fun(int &a, int &b)
{
if(b == )
{
throw "hello there have zero sorry\n"; //引发异常
}
return a / b;
}
int main()
{
int a;
int b;
while(true)
{
cin >> a;
cin >> b;
try //try里面是可能引发异常代码块
{
cout << " a / b = "<< fun(a,b) << "\n";
}
catch(const char *str) //接收异常,处理异常 括号内是类型
{
cout << str;
cerr <<"除数为0\n"; //cerr不会到输出缓冲中 这样在紧急情况下也可以使用
}
catch(...)//可以捕捉任何类型的异常
{
cerr <<"未知错误\n";
}
}
system("pause");
return ;//异常结束 }
try:try块标识符其中特定的异常可能被激活的代码块,他后面跟一个或者多个catch块.
catch:类似于函数定义,但并不是函数定义,关键字catch表明这是给一个处理程序, 里面的const cahr *str 会接受throw传过来错误信息.
throw:抛出异常信息,类似于执行返回语句,因为它将终止函数的执行,但是它不是将控制权交给调用程序,而是导致程序沿着函数调用序列后退,知道找到包含try块的函数.
(三)对segment_fault的处理
下面是来自Answers.com的定义:
|
A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. In short, a segmentation fault occurs when a program attempts to access a memory location that it is not allowed to access, or attempts to access a memory location in a way that is not allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based on processors like the Motorola 68000 tend to refer to these events as Address or Bus errors. |
另外,这里有个基本上对照的中文解释,来自http://www.linux999.org/html_sql/3/132559.htm
|
所谓的段错误 就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表, 后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中 就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访 问,cpu就会产生相应的异常保护,于是segmentation fault就出现了 |
实际上同前面一样,段错误也是访问到了非法的内存,它会抛出SIGSEGV信号,可以通过signal或者dev-c++自带调试器捕捉。
比如说:

其中scanf调用了a而不是&a
这时我们可以借助c++中的assert函数捕捉异常
首先我们初步判断这里出现了段错误,借助assert的异常判断我们可以看出是否出现错误

在判断确实出现错误以后我们可以借助调试器观察错误位置

经过观察,我们确定错误位于蓝色行的"%d",a处
改正就可以了
段错误是算法竞赛中很容易出现的一种错误,我们应该学会使用各种方法尽快加以解决。
关于c++中的Debug以及runtime_error之segment_fault的更多相关文章
- 怎样在myEclipse中使用debug调试程序?
怎样在myEclipse中使用debug调试程序? 最基本的操作是: 1.首先在一个java文件中设断点,然后debug as-->open debug Dialog,然后在对话框中选类 ...
- 在Salesforce中通过 Debug Log 方式 跟踪逻辑流程
在Salesforce中通过 Debug Log方式 跟踪逻辑流程 具体位置如下所示: Setup ---> Logs ---> Debug Logs ---> Monitored ...
- 在Intellij IDEA中使用Debug
Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化.通常我们也可以启用Debug模式来跟踪代码的运行流程去学习三方 ...
- 【技巧】Java工程中的Debug信息分级输出接口
也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...
- 【技巧】Java工程中的Debug信息分级输出接口及部署模式
也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...
- 在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示
在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示 当我们在VS的C++中使用vector.list.map等这些STL容器,在开启调试的时 ...
- VS中的Debug 和 Release 编译方式的本质区别
VS中的Debug 和 Release 编译方式的本质区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发布版本,它往往是进行了各种优化,使 ...
- 二十、在Intellij IDEA中使用Debug
Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化.通常我们也可以启用Debug模式来跟踪代码的运行流程去学习三方 ...
- Intellij IDEA中使用Debug
Intellij IDEA中使用Debug Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化.通常我们也可以启用 ...
随机推荐
- SSM导出报表为csv文件
报表导出思路为,在后台用iDataReader将查询得到的数据写进文件并压缩,向前端返回文件位置的链接,在前端执行下载操作. web端: 1. ajax请求url,将返回的路径json字符串解析并执行 ...
- U3D游戏开发商思考
代码驱动带来的技术题 游戏碎片化.U3D 引擎有个非常有力的特色,就是实时编译执行.这意味着不管在不论什么时候,仅仅要按下执行图标,当前的场景就会进入可执行状态. 这导致了游戏在开发的过程中常常陷入一 ...
- postgresql && .net core 使用空间数据
这里主要讲遇到的一些报错 增删改查 && 计算部分基本和sql server的空间数据操作一毛一样,感谢微软大大的倾情支持,直接看demo即可(- ̄▽ ̄)- 前往sql server ...
- QuickReport的OnNeedData的触发情况
1.设置QuickReport的DataSet为空.2.在QuickReport的BeforePrint里面将要显示的数据集合初始化,如Query1.First;3.在OnNeedData里面写代码, ...
- WPF 4 Ribbon 开发 之 应用程序菜单(Application Menu)
原文:WPF 4 Ribbon 开发 之 应用程序菜单(Application Menu) 在上一篇中我们完成了快捷工具栏的开发,本篇将讲解应用程序菜单开发的相关内容.如下图所示,点击程序窗 ...
- Qt 显示 GIF
Qt 中,静态图片 PNG,JPG 等可以用其创建 QPixmap,调用 QLabel::setPixmap() 来显示,但是能够具有动画的 GIF 却不能这么做,要在 QLabel 上显示 GIF, ...
- JAVASCRIPT高程笔记-------第八章 浏览器BOM对象
8.1 window对象--表示一个浏览器的实例 在全局作用域中声明的任何变量.函数都会变成window对象的属性和方法,与之直接定义window对象的属性的区别是 window.xxx 可以通过 ...
- jquery获取选中的值和设置单选扭选中
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- Java CLASSPATH 引发的问题
# 问题 在做 OJ 的时候,由于程序需要编译运行,出于安全性考虑,我选择利用类 ProcessBuilder ,一个通过命令行调用 Java 程序的类. 我在 Eclipse 中或者在 CMD 中执 ...
- C++中类的继承与Java中的不同,C++的派生类不能继承父类的构造函数和析构函数(不一定正确)
http://blog.csdn.net/guodongxiaren/article/details/24885023