Я создал следующий фрагмент кода, чтобы воспроизвести проблему с моим механизмом обработки ошибок в Unity C Test Framework.
Используя TEST_PROTECT(), как описано в документации по платформе Unity C Test, я не могу реализовать механизм обработки ошибок, который я делаю вручную в следующем примере.
Но я не знаю, чего мне не хватает.
#include <stdio.h>
#include <unity.h>
#include <signal.h>
#include <setjmp.h>
void setUp(void) {}
void tearDown(void) {}
static jmp_buf jump_buffer;
void segfault_handler(int signal)
{
longjmp(jump_buffer, 1); /* should I put UNITY_ABORT() here? */
}
int function_that_crashes(void)
{
int *val = NULL;
return *val;
}
void test_function_crash(void)
{
if (setjmp(jump_buffer) == 0) /* should I put TEST_PROTECT() here? */
{
signal(SIGSEGV, segfault_handler);
TEST_ASSERT_EQUAL_INT32(0, function_that_crashes());
}
else
{
TEST_FAIL_MESSAGE("[ERROR] Segmentation fault caught\n");
}
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_function_crash);
return UNITY_END();
}
Если я использую TEST_PROTECT и TEST_ABORT и проверяю код после замены макроса, все кажется эквивалентным коду, который я создал вручную. Но когда я запустил код, поведение было другим.
Если я удалю код, вводящий UB, проблема все равно останется, потому что, похоже, я неправильно настроил TEST_PROTECT и TEST_ABORT.
Я переписал вопрос.
Если у вас есть ответ, добавьте его как ответ, а не как дополнение к вопросу. Через несколько дней вы тоже можете принять ответ. Таким образом, вопрос кажется завершенным. Добавление ответа как части вопроса не дает такого завершения. См. Могу ли я ответить на свой вопрос?
хорошо спасибо! Я этого не знал.





В среде Unity C Test есть макрос TEST_PROTECT, который за кулисами вызывает setjmp, но в данном случае он не нужен, потому что никто не вызывает longjump.
Решение, которое, кажется, работает нормально, прикрепляет к сигналу SIGSEGV обработчик функции для завершения теста как неудачного, например. TEST_FAIL_MESSAGE("[ERROR] Segmentation fault caught");
segfault_handler прикрепляется к каждому тесту индивидуально с помощью функции тестового приспособления setUp.
В следующем примере есть несколько вызовов проблемных тестов, и все тесты завершаются неудачей без сбоя в работе системы.
#include <signal.h>
#include <unity.h>
void segfault_handler(int signal)
{
TEST_FAIL_MESSAGE("[ERROR] Segmentation fault caught");
}
void setUp(void)
{
signal(SIGSEGV, segfault_handler);
}
void tearDown(void) {}
int function_that_crashes(void)
{
int *val = NULL;
return *val;
}
void test_function_crash(void)
{
TEST_ASSERT_EQUAL_INT32(0, function_that_crashes());
}
int main(void)
{
UNITY_BEGIN();
RUN_TEST(test_function_crash);
RUN_TEST(test_function_crash);
RUN_TEST(test_function_crash);
return UNITY_END();
}
Ваш код вызывает неопределенное поведение путем разыменования нулевого указателя. Что произойдет, если вы это удалите?