Как создать коды, которые всегда запускают сигнал SIGFPE (деление на ноль)?

Мне нужно закодировать модульный тест, который всегда должен запускать сигнал, деленный на ноль (SIGFPE), чтобы я мог протестировать и сравнить, что произойдет с / без моего модуля улавливания сигналов.

Мой модуль перехвата / возобновления сигналов Linux был разработан и работал, как ожидалось. Когда я кодирую модульный тест для модуля, я сталкиваюсь с небольшой проблемой.

Это коды 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 ), "" );
};

Если все коды построены в режиме отладки, проблем нет. Но операция деления будет оптимизирована в режиме Release, в результате сигнал SIGFPE никогда не сработает!

Чтобы сохранить согласованность между кодами продуктов и кодами тестирования, я должен создать их все в режиме выпуска при выпуске продукта.

Как составить кусок кода, который всегда запускает сигнал SIGFPE?

Я не хочу использовать функцию raise (), если существует более актуальный метод, потому что я хочу активировать сигнал SIGFPE.

Спасибо! Пожалуйста, простите мой плохой английский!


person Leon    schedule 23.09.2020    source источник
comment
Вы пробовали просто объявить j в глобальной области видимости? Компилятор не может доказать, что j, даже если он инициализирован 0, не может быть изменен в другой единице перевода.   -  person Sam Varshavchik    schedule 23.09.2020
comment
Или, может быть, с использованием квалификатора volatile.   -  person anastaciu    schedule 23.09.2020
comment
Обычно, чтобы избежать такого рода проблем, вам нужно поместить часть вашего тестового кода в разные единицы компиляции, чтобы компилятор не мог оптимизировать между ними. Даже в этом случае у вас могут возникнуть проблемы, если вы включите оптимизацию времени компоновки.   -  person Chris Dodd    schedule 24.09.2020


Ответы (2)


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 (поэтому GCC 10 в сентябре 2020 г.) не могут определить содержимое файла /tmp/foobar во время выполнения (даже при сильной оптимизации, например, с помощью gcc -O3 -Wall).

Конечно, серьезный тестовый пример потребует заполнения этого /tmp/foobar сценария оболочки и использования некоторого Environment (7) для имени файла. См. Также mktemp (1), который будет использоваться в вашем тестировании. сценарий оболочки.

person Basile Starynkevitch    schedule 23.09.2020
comment
Проблема, вероятно, в том, что do_div_by_0 становится встроенным, а затем деление устраняется, потому что возвращаемое значение игнорируется, на что здесь не влияет дополнительный код ... - person Chris Dodd; 24.09.2020
comment
@ChrisDodd Да! Ты понял! Я пробовал по твоей подсказке! Это просто потому, что результат функции игнорируется, поэтому gcc всегда оптимизирует код деления! если я использую результат функции, он все равно не будет оптимизирован! - person Leon; 24.09.2020
comment
@ChrisDodd Не могли бы вы добавить официальный ответ? Думаю, мне стоит принять твой ответ. - person Leon; 24.09.2020

Я думаю, что ответ Криса Додда самый точный. Т.е. возвращаемое значение 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 ), "" );
};

Оно работает!

Спасибо всем!!!

person Leon    schedule 26.09.2020