【问题标题】:Signals and Division by Zero信号和除零
【发布时间】:2021-05-30 05:04:38
【问题描述】:

我在我的代码中得到了一个不需要的除零结果(代码是用 C++ 编写的):

#include <iostream>
#include <signal.h>
#include <fenv.h>

void div0(int signo, siginfo_t *info, void *ucontext)
{
    if(signo == SIGFPE && info->si_code == FPE_FLTDIV)
    {
        std::cout << "You can't divide numbers by 0, idiot!\n";
        exit(EXIT_FAILURE);
    }
}

int main()
{
    feenableexcept(FE_ALL_EXCEPT);

    struct sigaction act;
    act.sa_flags = SA_SIGINFO | SA_NODEFER;
    act.sa_sigaction = div0;

    int retn = sigaction(SIGFPE, &act, NULL);
    if(retn == -1)
    {
        perror("sigaction");
        return -1;
    }

    int n1, n2;

    std::cout << "Enter a number: ";
    std::cin >> n1;

    std::cout << "Enter another number to divide by: ";
    std::cin >> n2;

    double div = n1 / 1.0 / n2;
    std::cout << n1 << " / " << n2 << " = " << div << "\n";

    return 0;
}

当我在变量n2 中赋值0 时,结果是,例如:5 / 0 = inf。但我想得到:You can't divide numbers by zero, idiot!。我将SIGFPE 信号与FPE_FLTDIV 信号代码一起使用,并尝试将double 更改为float,但它仍然不起作用。我在互联网上搜索并没有找到任何解决方案。我错过了什么?感谢您的帮助。

【问题讨论】:

  • 首先,你是如何编译你的程序的?而且您不能在信号处理程序中安全地使用cout。每footnote 188 of the C11 standard:“因此,信号处理程序通常不能调用标准库函数。” POSIX 允许您调用异步信号安全函数,但 cout 不是其中之一。 Linux provides a list Linux 特定的异步信号安全功能。如果它不在该列表中,则无法在信号处理程序中安全地使用它 - 这意味着没有 C++ 流...
  • @AndrewHenle 那么哪个 IO 函数是信号安全的?我用 g++ 编译程序。
  • write()。就是这样。没有 C++ 流,甚至没有 fprintf()fwrite()。你甚至可以在像这样的小程序中使用cout(大多数时候......),但是当事情变得更复杂时,它就会变得危险。
  • 我不知道这是否与此处相关,但通常,浮点错误不会引发任何信号 - 结果只是 NaN。您可能还需要更改一些浮点设置。
  • @PMF 使用 GCC,这可能取决于编译选项。见gcc.gnu.org/wiki/FloatingPointMath

标签: c++ linux signals posix divide-by-zero


【解决方案1】:

为什么不尝试简单的if (n2 == 0) std::cout &lt;&lt; "You can't divide numbers by zero, i***t!"

另一种方法是if isnan(div) std::cout &lt;&lt; "You already divided by zero, i***t!"

doublefloat 中,0/0 部分是静默的。您将收到NaN,而不是任何异常。这将使您能够更好地处理错误。

添加到评论中

如果要生成信号,则需要将所有变量都用作integer,并避免编译器进行优化。 《Linux 编程接口》一书中有很好的例子you can find here

【讨论】:

  • 我在 Linux 中学习信号,所以我必须使用信号来做。
  • @Matan 我用一个链接更新了答案,该链接指向一个生成 SIGFPE 的示例
猜你喜欢
  • 2013-01-25
  • 1970-01-01
  • 2015-06-21
  • 1970-01-01
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多