如何生成始终触发信号 SIGFPE(除以零)的代码?

问题描述 投票:0回答:2

我需要编写一个单元测试,该测试应该始终触发除以零的信号(SIGFPE),这样我就可以测试并比较使用/不使用信号捕获模块时会发生什么。

我的Linux信号捕捉/恢复模块已经开发完成,并且工作正常。当我为模块编写单元测试时,我遇到了一个小麻烦。

这些是 UT 代码(通过 GTest):

int do_div_by_0() {
    int j = 0;
    return 123 / j; /* During release-building, this div-op would be optimized out,
                       although it would be not when debug-building! */
};

TEST_F( SignalsHandling_F, divByZeroDying ) {
   ASSERT_EXIT( {
      do_div_by_0();
      
      // never should go here!
      exit( EXIT_SUCCESS );

   }, KilledBySignal( SIGFPE ), "" );
};

如果所有代码都是在Debug模式下构建的,就没有问题。但是除法运算会在Release模式下被优化,因此SIGFPE信号永远不会被触发!

为了保持产品代码和测试代码的一致性,我在发布产品时必须将它们全部以发布模式构建。

如何编写一段始终触发SIGFPE信号的代码?

如果存在更“实际”的方法,我不想使用 raise() 函数,因为我想实际触发 SIGFPE 信号。

c++ unit-testing optimization divide-by-zero sigfpe
2个回答
0
投票
int do_div_by_0() {
   int j = 0;
   FILE *f = fopen("/tmp/foobar",  "r");
   if (f) {
     fscanf(f, "%d", &j);
     fclose(f);
   };
   return 123 / j; /* During release-buidling, this div-op would be optimized out,
                   although it would be not when debug-building! */
};

可能是一个解决方案。当前的 GCC 编译器(因此 2020 年 9 月的 GCC 10)无法在运行时找出文件

/tmp/foobar
的内容(即使使用
gcc -O3 -Wall
等进行强烈优化)。

当然,一个严格的测试用例将涉及一些 shell 脚本填充该

/tmp/foobar
并使用一些 environ(7) 变量作为文件名。另请参阅要在测试 shell 脚本中使用的 mktemp(1)


0
投票

我认为ChrisDodd的答案是最准确的。 IE。 do_div_by_0 的返回值被忽略,以便编译器优化除法运算

我们需要在调用do_div_by_0时使用返回值,如下:

TEST_F( SignalsHandling_F, divByZeroDying ) {
   ASSERT_EXIT( {
      std::cerr << do_div_by_0();
      
      // never should go here!
      exit( EXIT_SUCCESS );

   }, KilledBySignal( SIGFPE ), "" );
};

有效!

© www.soinside.com 2019 - 2024. All rights reserved.