如何在MinGW gcc中捕获断言失败?

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

在Unix系统上,我可以使用fork()产生一个进程,并检查该线程的标志以判断该线程是否中止(通常是通过断言失败)。这是给定一个函数的示例代码,检查该函数调用是否中止。

bool test_assert_fail(void (*run)(void *aux), void *aux) {
    if (fork()) { // parent process
        int *status = malloc(sizeof(*status));
        assert(status != NULL);
        wait(status);
        // Check whether child process aborted
        bool aborted = WIFSIGNALED(*status) && WTERMSIG(*status) == SIGABRT;
        free(status);
        return aborted;
    }
    else { // child process
        freopen("/dev/null", "w", stderr); // suppress assertion message
        run(aux);
        exit(0); // should not be reached
    }
}

使用MinGW gcc编译器在Windows上执行类似操作的最简单方法是什么?线程不起作用,因为子线程中止会导致父线程也中止。我不知道该如何使用进程,因为它是一个函数调用。

c mingw assert mingw-w64
1个回答
0
投票

NB:与此一起调用的函数非常简单并且是单线程的,因此它比通常要安全[[有点]]。我最终使用signal捕获SIGABRT,并使用longjmp继续执行:

#ifdef _WIN32 bool SIGABRT_RAISED = false; jmp_buf env; void signal_handler(int signum) { if (signum == SIGABRT) { SIGABRT_RAISED = true; // Reregister default, and jump out to avoid return signal(signum, SIG_DFL); longjmp(env, 1); } } #endif bool test_assert_fail(void (*run)(void *aux), void *aux) { // Windows can't use POSIX apis #ifndef _WIN32 if (fork()) { // parent process int *status = malloc(sizeof(*status)); assert(status != NULL); wait(status); // Check whether child process aborted bool aborted = WIFSIGNALED(*status) && WTERMSIG(*status) == SIGABRT; free(status); return aborted; } else { // child process freopen("/dev/null", "w", stderr); // suppress assertion message run(aux); exit(0); // should not be reached } #else signal(SIGABRT, signal_handler); SIGABRT_RAISED = false; int cstderr = _dup(_fileno(stderr)); // Run expected failure, jumping back when SIGABRT is raised if (setjmp(env) == 0) { // suppress assertion message freopen("NUL", "w", stderr); run(aux); } // Undo suppression, since we are in the same process _dup2(cstderr, _fileno(stderr)); return SIGABRT_RAISED; #endif }

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