How can I assert() without using abort()?

后端 未结 6 1031
失恋的感觉
失恋的感觉 2020-12-08 20:06

If I use assert() and the assertion fails then assert() will call abort(), ending the running program abruptly. I can\'t afford that

6条回答
  •  醉梦人生
    2020-12-08 20:35

    glib's error reporting functions take the approach of continuing after an assert. glib is the underlying platform independence library that Gnome (via GTK) uses. Here's a macro that checks a precondition and prints a stack trace if the precondition fails.

    #define RETURN_IF_FAIL(expr)      do {                  \
     if (!(expr))                                           \
     {                                                      \
             fprintf(stderr,                                \
                    "file %s: line %d (%s): precondition `%s' failed.", \
                    __FILE__,                                           \
                    __LINE__,                                           \
                    __PRETTY_FUNCTION__,                                \
                    #expr);                                             \
             print_stack_trace(2);                                      \
             return;                                                    \
     };               } while(0)
    #define RETURN_VAL_IF_FAIL(expr, val)  do {                         \
     if (!(expr))                                                       \
     {                                                                  \
            fprintf(stderr,                                             \
                    "file %s: line %d (%s): precondition `%s' failed.",     \
                    __FILE__,                                               \
                    __LINE__,                                               \
                    __PRETTY_FUNCTION__,                                    \
                    #expr);                                                 \
             print_stack_trace(2);                                          \
             return val;                                                    \
     };               } while(0)
    

    Here's the function that prints the stack trace, written for an environment that uses the gnu toolchain (gcc):

    void print_stack_trace(int fd)
    {
        void *array[256];
        size_t size;
    
        size = backtrace (array, 256);
        backtrace_symbols_fd(array, size, fd);
    }
    

    This is how you'd use the macros:

    char *doSomething(char *ptr)
    {
        RETURN_VAL_IF_FAIL(ptr != NULL, NULL);  // same as assert(ptr != NULL), but returns NULL if it fails.
    
        if( ptr != NULL )        // Necessary if you want to define the macro only for debug builds
        {
           ...
        }
    
        return ptr;
    }
    
    void doSomethingElse(char *ptr)
    {
        RETURN_IF_FAIL(ptr != NULL);
    }
    

提交回复
热议问题