ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
26 февраля
1572622 Топик полностью
SciFi (Вчера, 22:04, просмотров: 30) ответил Dingo на assert сильно перекликается, но они при NDEBUG отключаются вроде как везде, а тут выборочно можно. юнит-тесты не освоил :-(
Нагородить макросы вокруг assert() для выборочности нетрудно, было бы желание. Нынче ИИ это делает легко и просто. 

если что, я не проверял на предмет глюков

/* debug_assert.h — модифицированный assert() для C99 с несколькими уровнями
 * 
 * Уровень проверок задаётся при компиляции:
 *     gcc -DASSERT_LEVEL=2 ...
 * 
 * ASSERT_LEVEL = 0  → все ASSERT() полностью удаляются (как NDEBUG)
 * ASSERT_LEVEL = 1  → работают только ASSERT(1, ...)
 * ASSERT_LEVEL = 2  → работают ASSERT(1, ...) и ASSERT(2, ...)
 * ASSERT_LEVEL = 3  → работают уровни 1-3
 * и т.д. (можно добавить сколько угодно уровней)
 * 
 * Преимущества:
 * • Полностью compile-time отключение — код и вычисление выражений исчезают.
 * • Нет runtime-if даже в отладке (компилятор видит только нужные макросы).
 * • Совместимо со стандартным assert() (можно использовать параллельно).
 * • Красивое сообщение с уровнем, функцией, файлом и строкой.
 */
#ifndef DEBUG_ASSERT_H
#define DEBUG_ASSERT_H
#include <stdio.h>
#include <stdlib.h>
/* По умолчанию — release-режим (всё выключено) */
#ifndef ASSERT_LEVEL
#  define ASSERT_LEVEL 0
#endif
/* Если кто-то определил NDEBUG — принудительно выключаем всё */
#ifdef NDEBUG
#  undef ASSERT_LEVEL
#  define ASSERT_LEVEL 0
#endif
/* ================================================================ */
/* Вспомогательные макросы для генерации ASSERT_1, ASSERT_2, ...    */
/* ================================================================ */
#define ASSERT_CAT(x, y) x ## y
#define ASSERT_CAT2(x, y) ASSERT_CAT(x, y)
/* Макрос, который будет расширяться в ASSERT_1, ASSERT_2 и т.д. */
#define ASSERT(lvl, expr) ASSERT_CAT2(ASSERT_, lvl)(expr)
/* ================================================================ */
/* Генерация каждого уровня (добавляйте новые уровни сюда)         */
/* ================================================================ */
#if ASSERT_LEVEL >= 1
#  define ASSERT_1(expr) \
    do { \
        if (!(expr)) { \
            fprintf(stderr, \
                "ASSERT(1) failed: %s\n" \
                "    function: %s\n" \
                "    file:     %s:%d\n", \
                #expr, __func__, __FILE__, __LINE__); \
            abort(); \
        } \
    } while (0)
#else
#  define ASSERT_1(expr) ((void)0)
#endif
#if ASSERT_LEVEL >= 2
#  define ASSERT_2(expr) \
    do { \
        if (!(expr)) { \
            fprintf(stderr, \
                "ASSERT(2) failed: %s\n" \
                "    function: %s\n" \
                "    file:     %s:%d\n", \
                #expr, __func__, __FILE__, __LINE__); \
            abort(); \
        } \
    } while (0)
#else
#  define ASSERT_2(expr) ((void)0)
#endif
#if ASSERT_LEVEL >= 3
#  define ASSERT_3(expr) \
    do { \
        if (!(expr)) { \
            fprintf(stderr, \
                "ASSERT(3) failed: %s\n" \
                "    function: %s\n" \
                "    file:     %s:%d\n", \
                #expr, __func__, __FILE__, __LINE__); \
            abort(); \
        } \
    } while (0)
#else
#  define ASSERT_3(expr) ((void)0)
#endif
#if ASSERT_LEVEL >= 4
#  define ASSERT_4(expr) \
    do { \
        if (!(expr)) { \
            fprintf(stderr, \
                "ASSERT(4) failed: %s\n" \
                "    function: %s\n" \
                "    file:     %s:%d\n", \
                #expr, __func__, __FILE__, __LINE__); \
            abort(); \
        } \
    } while (0)
#else
#  define ASSERT_4(expr) ((void)0)
#endif
/* Добавляйте сюда ASSERT_5, ASSERT_6 … сколько нужно */
/* ================================================================ */
/* Удобные алиасы (по желанию)                                      */
/* ================================================================ */
#define ASSERT_CRITICAL(expr)   ASSERT(1, expr)   /* всегда включено при ASSERT_LEVEL >= 1 */
#define ASSERT_NORMAL(expr)     ASSERT(2, expr)
#define ASSERT_HEAVY(expr)      ASSERT(3, expr)   /* тяжёлые проверки */
#define ASSERT_PARANOID(expr)   ASSERT(4, expr)   /* параноидальные проверки */
/* Если хочется использовать старый assert() как ASSERT(1, ...) */
#if ASSERT_LEVEL >= 1
#  undef assert
#  define assert(expr) ASSERT(1, expr)
#else
#  undef assert
#  define assert(expr) ((void)0)
#endif
#endif /* DEBUG_ASSERT_H */


/////////////////////////////////////////////////////

#include "debug_assert.h"
void example(int *ptr, size_t n) { ASSERT(1, ptr != NULL); // критическая проверка ASSERT(2, n < 1000); // обычная ASSERT(3, is_valid_data(ptr, n)); // тяжёлая (включается только при -DASSERT_LEVEL=3) ASSERT_PARANOID(n % 8 == 0); // совсем параноидальная // Можно и классический assert, если хочется assert(ptr != NULL); }
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้