差不多每次编一些竞赛类的程序都会至少给我报一次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.
Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging for most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.
On Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. On Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.

   另外,这里有个基本上对照的中文解释,来自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函数的用法自己看

    首先我们初步判断这里出现了段错误,借助assert的异常判断我们可以看出是否出现错误

    

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

    

    经过观察,我们确定错误位于蓝色行的"%d",a处

    改正就可以了


段错误是算法竞赛中很容易出现的一种错误,我们应该学会使用各种方法尽快加以解决。

关于c++中的Debug以及runtime_error之segment_fault的更多相关文章

  1. 怎样在myEclipse中使用debug调试程序?

    怎样在myEclipse中使用debug调试程序? 最基本的操作是:     1.首先在一个java文件中设断点,然后debug as-->open debug Dialog,然后在对话框中选类 ...

  2. 在Salesforce中通过 Debug Log 方式 跟踪逻辑流程

    在Salesforce中通过 Debug Log方式 跟踪逻辑流程 具体位置如下所示: Setup ---> Logs ---> Debug Logs ---> Monitored ...

  3. 在Intellij IDEA中使用Debug

    Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化.通常我们也可以启用Debug模式来跟踪代码的运行流程去学习三方 ...

  4. 【技巧】Java工程中的Debug信息分级输出接口

    也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...

  5. 【技巧】Java工程中的Debug信息分级输出接口及部署模式

    也许本文的标题你们没咋看懂.但是,本文将带大家领略输出调试的威力. 灵感来源 说到灵感,其实是源于笔者在修复服务器的ssh故障时的一个发现. 这个学期初,同袍(容我来一波广告产品页面,同袍官网)原服务 ...

  6. 在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示

    在Visual Studio中使用Debug Visualizers在C++中实现对原始类的自定义调试信息显示 当我们在VS的C++中使用vector.list.map等这些STL容器,在开启调试的时 ...

  7. VS中的Debug 和 Release 编译方式的本质区别

    VS中的Debug 和 Release 编译方式的本质区别 Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序.Release 称为发布版本,它往往是进行了各种优化,使 ...

  8. 二十、在Intellij IDEA中使用Debug

    Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化.通常我们也可以启用Debug模式来跟踪代码的运行流程去学习三方 ...

  9. Intellij IDEA中使用Debug

    Intellij IDEA中使用Debug Debug用来追踪代码的运行流程,通常在程序运行过程中出现异常,启用Debug模式可以分析定位异常发生的位置,以及在运行过程中参数的变化.通常我们也可以启用 ...

随机推荐

  1. C#操作EXCEL常见操作集合(行高,列宽,合并单元格,单元格边框线)

    private _Workbook _workBook = null; private Worksheet _workSheet = null; private Excel.Application _ ...

  2. Qt5.8 下链接 Mysql 错误以及解决方法(无论 Mysql 是什么版本的,64 位 Qt 要用 64 位的 Mysql 驱动,32 位的 Qt 要用 32 位的Mysql 驱动)

    Qt 5.8 下链接 Mysql(Windows 平台下),有朋友会出现一个这个无法连接的错误 QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: ...

  3. 去掉 Windows 中控件的虚线框(当当 element == QStyle::PE_FrameFocusRect 时,直接返回,不绘制虚线框)

    在 Windows 中,控件得到焦点的时候,会显示一个虚线框,很多时候觉得不好看,通过自定义 QProxyStyle 就可以把这个虚线框去掉. 1 2 3 4 5 6 7 8 9 10 11 12 1 ...

  4. Servlet的基础知识

    没有什么固定的结构, 就是稍微总结一下学习到的, 基本上想到哪里写到哪里. 关于基本的最HttpServlet 实际上Servlet是J2EE(也就是现在的Java EE)中规范的一个接口, 用于根据 ...

  5. n阶贝塞尔曲线绘制(C/C#)

    原文:n阶贝塞尔曲线绘制(C/C#) 贝塞尔是很经典的东西,轮子应该有很多的.求n阶贝塞尔曲线用到了 德卡斯特里奥算法(De Casteljau's Algorithm) 需要拷贝代码请直接使用本文最 ...

  6. Mvvm Light Toolkit 入门

    原文:Mvvm Light Toolkit 入门 前言 之前学习UWP的时候就一直看到有关MVVM的资料但是一直没有系统的去学,最近正好有时间,特地来攻破这个点,顺便学习一下VS与GitHub的链接和 ...

  7. 加快QT工程编译速度(还可给Qt for Android设置)

    一.多核编译 环境:win10, Qt 5.4.1,编译器mingw32 项目: Qt for Android Qt Creator 在编译android项目时不支持预编译,默认cpu单核编译,工程稍 ...

  8. 【C#】简单解决PathTooLong的Exception

    原文:[C#]简单解决PathTooLong的Exception 前提 windows系统路径的最大长度限制是260个字符(听说.Net 4.6.2,取消了这个限制),而Linux或者Unix系统的好 ...

  9. 微信小程序把玩(十)swiper组件

    原文:微信小程序把玩(十)swiper组件 Android写过轮播图的痛楚只有写过的知道,相对还是比较麻烦的,并没有一个轮播图组件,有个ViewPage也需要自己定制,IOS则多用UIScroller ...

  10. windows界面程序设计,设置一个窗口始终在屏幕最前,SetWindowPos函数

    有时这种需求还是很必须的,比如现在做的一个登录验证系统,如果在windows登录界面点击到窗口外面,那窗口就会永远隐藏掉没法再启用了.这种情况必须设置该窗口一直在最前. 使用函数SetWindowPo ...