How to Capture the Integer-Divide-By-Zero Error in C++?

MANUAL CAPTURE

The simple and straightforward method is to check it manually if possible. The following outputs “got you!”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// https://helloacm.com
#include <iostream>
using namespace std;
 
int main() {
    try {
        int x = 1, y = 0;
        if (y == 0) {
                throw "error";
        }
        cout << x / y;
    } catch (...) {
        cerr << "got you!";
    }
    return 0;
}

However, it is tedious and not-so-elegant to place checks at each possible code occurrence and we want to the program to handle this.

TRY-CATCH DOES NOT CATCH INT-DIVIDE-BY-ZERO ERROR

The first thought would be to put the possible divide-by-zero code in side a try-catch, like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
// https://helloacm.com
#include <iostream>
using namespace std;
 
int main() {
    try {
        int x = 1, y = 0;
        cout << x / y;
    } catch (...) {
        cerr << "got you!";
    }
    return 0;
}

However, when you compile the above code using g++ compiler and run it, the error says Floating point exception instead of the customize error message in try-catch. This means that the error is not caught by try-catch.

USING SIGNAL

At Linux, we can set up signals to capture the error. In this case, the error type is SIGFPE which stands for Signal Float Point Exceptions. The function to set up a signal is signal and it takes two parameters, the signal type and the function to handle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// https://helloacm.com
#include <iostream>
#include <cstdlib>
#include <csignal>
 
using namespace std;
 
void error(int) {
    cerr << "got you!";
    exit(1);
}
 
int main() {
    if (SIG_ERR == signal(SIGFPE, error)) {
        cerr << "failure to setup signal.";
        return 1;
    }
    int x = 1, y = 0;
    cout << x / y;
    return 0;
}

In short, the when SIGFPE signal is caught, the error function will be invoked to deal with the error. The exit(1) function is important here. In case if you just simply return from the error-handling-function, the disaster happens with an endless loop, which prints “got you!” repeatedly until you ctrl+C to abort/kill it.

When error happens, the OS call the stack of the error function, and set its return address just right before the int-div-by-zero. Virtually, the error-function is invoked right before the error occurs. And after the error-function returns, it will again meet the code that triggers the error, which is why it will keep printing the error.

Some might’ve thought to fix this by making the y variable the global and set to 1 inside the error function. However, this does not help. It seems that the error still occurs regardless the value of y.

1
2
3
4
5
6
// https://helloacm.com
int y = 0; // global variable
void error(int) {
    cerr << "got you!";
    y = 1; // set to 1 to fix it, but this does not work, why?
}

USING EXCEPTIONS

We could easily replace above exit() with the exceptions to throw in the error function:

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
// https://helloacm.com
#include <iostream>
#include <cstdlib>
#include <csignal>
 
using namespace std;
struct div_0_exception {};
 
void error(int) {
    throw div_0_exception();
}
 
int main() {
    if (SIG_ERR == signal(SIGFPE, error)) {
        cerr << "failure to setup signal.";
        return 1;
    }
    try {
        int x = 1, y = 0;
        cout << x / y;
    } catch (div_0_exception) {
        cout << "got you!";
    }
    return 0;
}

USING CUSTOMIZED SIGNAL

The above throws regardless the type of float point exceptions. The POSIX defines a more comprenhensive signal processing interface, i.e. sigaction, which is defined in csignal header.

1
2
3
4
5
6
7
// https://helloacm.com
struct sigaction;
 
int sigaction(int sig,
              struct sigaction const* restrict act,
              struct sigaction* restrict old_act
);

Please note that, these two have the same identifies. The first one is the structure type that stores some function pointers. And the second is the actual function entry to set up the signal. The third parameter is usually set to NULL, for more information, read man 3 sigaction.

The sigaction structure has two function entry points:

1
2
void (* sa_handler)(int);
void (* sa_sigaction)(int, siginfo_t*, void*);

The first entry is the light-weight handling method, which has been shown in previous code examples. The second one allows more information in the code context. Based on the second parameter, we could pass the additional information via sa_flags. Possible si_code values: FPE_INTOVF (integer overflow), FPE_FLTUND (float underflow), FPE_FLTOVF (float overflow) and what we care about – the FPT_INTDIV.

Let’s look at the complete example of C++ using comprehensive signal to catch the integer-divided-by-zero error.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// https://helloacm.com
#include <iostream>
#include <cstdlib>
#include <csignal>
 
struct my_sig_action {
    typedef void (* handler_type)(int, siginfo_t*, void*);
 
    explicit my_sig_action(handler_type handler)
    {
        memset(&_sa, 0, sizeof(struct sigaction));
        _sa.sa_sigaction = handler;
        _sa.sa_flags = SA_SIGINFO;
    }
 
    operator struct sigaction const*() const
    {
        return &_sa;
    }
protected:
    struct sigaction _sa;
};
 
struct div_0_exception {};
 
void error(int sig, siginfo_t* info, void*) {
    if (FPE_INTDIV == info->si_code)
        throw div_0_exception();
}
 
int main()
{
    my_sig_action sa(error);
    if (0 != sigaction(SIGFPE, sa, NULL)) {
        cerr << "failure to setup signal.";
        return 1;
    }
    try {
        int x = 1, y = 0;
        cout << x / y;
    } catch (div_0_exception) {
        cout << "got you!";
    }
    return 0;
}

–EOF (The Ultimate Computing & Technology Blog) —

https://helloacm.com/how-to-capture-the-integer-divide-by-zero-error-in-c/

How to Capture the Integer-Divide-By-Zero Error in C++(提前定义信号)的更多相关文章

  1. Integer比较

    /** * @time 2014-06-25 * @author Cao HaiCheng * */ public class demo { public static void main(Strin ...

  2. Integer判等的陷阱:你知道Integer内部高速缓冲区IntegerCache吗?

    https://blog.csdn.net/magician_Code/article/details/51469101 我们先来看看下面代码的运行情况: public static void mai ...

  3. IntegerCache缓存占用堆、栈、常量池的问题,自动拆装箱的基本概念,Integer==int时的问题说明

    原创声明:作者:Arnold.zhao 博客园地址:https://www.cnblogs.com/zh94 先普及一个基本概念:Java中基本数据类型的装箱和拆箱操作 自动装箱 在JDK5以后,我们 ...

  4. PHP7函数大全(4553个函数)

    转载来自: http://www.infocool.net/kb/PHP/201607/168683.html a 函数 说明 abs 绝对值 acos 反余弦 acosh 反双曲余弦 addcsla ...

  5. SQL注入备忘单

    Find and exploit SQL Injections with free Netsparker SQL Injection Scanner SQL Injection Cheat Sheet ...

  6. Windows SEH学习 x86

    windows 提供的异常处理机制实际上只是一个简单的框架.我们通常所用的异常处理(比如 C++ 的 throw.try.catch)都是编译器在系统提供的异常处理机制上进行加工了的增强版本.这里先抛 ...

  7. 7系列FPGA的时钟资源——UG472

    时钟架构总览 7系的FPGA使用了专用的全局(Global)和区域(Regional)IO和时钟资源来管理设计中各种的时钟需求.Clock Management Tiles(CMT)提供了时钟合成(C ...

  8. IBM DB2 SQL error code list

    SQL return codes that are preceded by a minus sign (-) indicate that the SQL statement execution was ...

  9. leetcode 学习心得 (1) (24~300)

    源代码地址:https://github.com/hopebo/hopelee 语言:C++ 24.Swap Nodes in Pairs Given a linked list, swap ever ...

随机推荐

  1. 【b304】传染病防治

    Time Limit: 1 second Memory Limit: 50 MB [问题背景] 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国 大范围流行,该国政府决定不惜 ...

  2. 机房重构所遇问题&quot;未能载入文件或程序集“DAL”或它的某一个依赖项。系统找不到指定的文件&quot;的解决的方法集锦

    敲七层登录的时候.忽然间认为敲三层搞清的思路瞬间又凌乱了.花了一天的时间边敲边梳理,最终整完了,执行的时候弹出了这种错误:未能载入文件或程序集"DAL"或它的某一个依赖项. 系统找 ...

  3. python request post

    import requests import json class BaiduTranslateSpider: def __init__(self, kw): self.url = "htt ...

  4. 【21.21%】【codeforces round 382D】Taxes

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  5. Delphi绘图相关对象(TCanvas对象的方法)

    TCanvas对象的方法 方法 说明 Arc Arc(x1,y1,x2,y2,x3,y3,x4,y4 : Integer); Arc方法在椭圆上画一段弧,椭圆由(x1,y1).(x2,y2) 两点所确 ...

  6. 判断软件的闲置时间(使用Application.OnMessage过滤所有键盘鼠标消息)

    GetLastInputInfo是检测系统输入的,应用到某个程序中不合适! 此问题有二种解法来监控输入消息: 1.用线程级HOOK,钩上MOUSEHOOK与KEYBOARDHOOK 2.在Applic ...

  7. Android framework召回(3)binder使用和IBinder BpRefbase IInterface INTERFACE 之间的关系

    status_t AudioSystem::setStreamVolumeIndex(audio_stream_type_t stream, int index, audio_devices_t de ...

  8. 乞讨 间隔[a,b]在见面p^k*q*^m(k&gt;m)中数号码

    标题叙述性说明: 1<=a,b<=10^18,p,q他们是素数  2<=p,q<=10^9; 求在[a,b]内能够表示为  x*p^k*q^m  k > m   的数的个 ...

  9. Linux性能测试 ss命令

    ss即socket state,也就是说,是可以查看系统中socket的状态的.我们可以用netstat,但为什么还要用ss这个工具呢,当然ss也是有好处的.当我们打开的socket数量很多时,net ...

  10. ASP.NET Core 使用 EF 框架查询数据 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 使用 EF 框架查询数据 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 使用 EF 框架查询数据 上一章节我们学习了如何设置 ...