如何生成始终触发信号 SIGFPE(div 为零)的代码?
How to produce codes that always trigger signal SIGFPE(div by zero)?
我需要编写一个单元测试,它应该始终触发除以零的信号 (SIGFPE),这样我就可以测试和比较会发生什么 with/without 我的信号捕捉模块。
我的 Linux 信号 catching/resuming 模块已经开发,并且按预期工作。
在编写模块的单元测试代码时,遇到了一个小麻烦。
这些是UT代码(通过GTest):
int do_div_by_0() {
int j = 0;
return 123 / j; /* During release-buidling, 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 信号。
谢谢!请原谅我糟糕的英语!
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 compilers (so GCC 10 在 2020 年 9 月)无法在运行时找出文件 /tmp/foobar
的内容(即使使用 gcc -O3 -Wall
等进行了强烈优化)。
当然,一个严肃的测试用例会涉及一些 shell 脚本来填充 /tmp/foobar
并使用一些 environ(7) variable for the file name. See also mktemp(1) 用于测试 shell 脚本。
我认为 ChrisDodd 的回答是最准确的。
IE。 do_div_by_0 的 return 值被忽略,因此编译器优化了除法操作。
我们在调用do_div_by_0时需要使用return值,如下:
TEST_F( SignalsHandling_F, divByZeroDying ) {
ASSERT_EXIT( {
std::cerr << do_div_by_0();
// never should go here!
exit( EXIT_SUCCESS );
}, KilledBySignal( SIGFPE ), "" );
};
有效!
谢谢大家!!!
我需要编写一个单元测试,它应该始终触发除以零的信号 (SIGFPE),这样我就可以测试和比较会发生什么 with/without 我的信号捕捉模块。
我的 Linux 信号 catching/resuming 模块已经开发,并且按预期工作。 在编写模块的单元测试代码时,遇到了一个小麻烦。
这些是UT代码(通过GTest):
int do_div_by_0() {
int j = 0;
return 123 / j; /* During release-buidling, 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 信号。
谢谢!请原谅我糟糕的英语!
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 compilers (so GCC 10 在 2020 年 9 月)无法在运行时找出文件 /tmp/foobar
的内容(即使使用 gcc -O3 -Wall
等进行了强烈优化)。
当然,一个严肃的测试用例会涉及一些 shell 脚本来填充 /tmp/foobar
并使用一些 environ(7) variable for the file name. See also mktemp(1) 用于测试 shell 脚本。
我认为 ChrisDodd 的回答是最准确的。 IE。 do_div_by_0 的 return 值被忽略,因此编译器优化了除法操作。
我们在调用do_div_by_0时需要使用return值,如下:
TEST_F( SignalsHandling_F, divByZeroDying ) {
ASSERT_EXIT( {
std::cerr << do_div_by_0();
// never should go here!
exit( EXIT_SUCCESS );
}, KilledBySignal( SIGFPE ), "" );
};
有效!
谢谢大家!!!