Обеспечить проверку состояния перед блоками кода C

Короткая история: я хочу обеспечить проверку условий во время выполнения в определенных условно скомпилированных блоках кода, но не в других.

Длинная история: наша база кода C в значительной степени опирается на профилирование. У нас много разных профилей, и почти каждый модуль имеет #ifdefs для как минимум 5-6 различных профилей, оборачивая большие сегменты кода.

Мы добавили новое требование - для определенных профилей (скажем, <A> а также <B>), условно скомпилированный код будет выполняться только при соблюдении определенного условия. Для других профилей (скажем, <C>) это не обязательно.

то есть, вот как выглядит код:

#ifdef <A>
    /* Profiled code… */
#endif /* <A> */

#ifdef <B>
    /* Profiled code… */
#endif /* <B> */

#ifdef <C>
    /* Profiled code… */
#endif /* <C> */

Вот как мы должны выглядеть:

#ifdef <A>
    if (new_condition)
    {
        /* Profiled code… */
    }
#endif /* <A> */

#ifdef <B>
    if (new_condition)
    {
        /* Profiled code… */
    }
#endif /* <B> */

#ifdef <C>
    /* Profiled code… */
#endif /* <C> */

Все идет нормально.

Тем не менее, с вышеупомянутой реализацией новое требование на самом деле не подлежит обслуживанию. Это не мешает никому не знакомому с требованием добавить новый блок профилированного кода, не добавляя проверку для new_condition,

Поэтому я хочу заставить наших инженеров проверять это условие всякий раз, когда добавляются новые блоки, которые профилируются под <A> а также <B>, но не для кода, профилированного под <C>,

Теоретически, наилучшим решением, вероятно, будет выход из строя процесса сборки, если существует #ifdef <A> или же #ifdef <B> это непосредственно не сопровождается if (new_condition),

Дело в том, что я понятия не имею, чтобы сделать это. У кого-нибудь из вас есть?

3 ответа

Одна идея, которая поддерживает ваш текущий макрос начала, блоки стиля конца макроса могут выглядеть примерно так:

#include <stdio.h>

#define FOO 1
#define BAZ 1

int condition_a = 1;
int condition_b = 0;

#ifdef FOO
#  define FOO_BEGIN if (condition_a) {
#  define FOO_END }
#else
#  define FOO_BEGIN if (0) {
#  define FOO_END }
#endif

#ifdef BAR
#  define BAR_BEGIN if (condition_b) {
#  define BAR_END }
#else
#  define BAR_BEGIN if (0) {
#  define BAR_END }
#endif

#ifdef BAZ
#  define BAZ_BEGIN if (1) {
#  define BAZ_END }
#else
#  define BAZ_BEGIN if (0) {
#  define BAZ_END }
#endif

int main (int argc, char ** argv)
{
    FOO_BEGIN
        printf("in foo\n");
    FOO_END

    BAR_BEGIN
        printf("in bar\n");
    BAR_END

    BAZ_BEGIN
        printf("in baz\n");
    BAZ_END
}

печать

in foo
in baz

Вам придется либо обновить макросы, которые определяют входящие и выходящие блоки, либо требовать что-то внутри этих ifdef.

Сложно ответить на это, поскольку все так нечетко:) Но я бы предложил использовать какую-то оболочку, которую редактору кода не разрешено изменять:

typedef void(*stuff_ptr)(void);

inline void do_stuff (stuff_ptr stuff)
{
  #if defined(A) || defined(B)
  if (!new_condition)
  {
    return ;
  }
  #endif

  stuff();
}

#ifdef A
  do_stuff(A_stuff);
#endif

#ifdef B
  do_stuff(B_stuff);
#endif

#ifdef C
  do_stuff(C_stuff);
#endif

Это не прекратит сборку, но вместо этого предотвратит неправильные сборки в первую очередь.

При необходимости do_stuff() может быть реализован как функциональный макрос, но избегайте этого, если можете. "New_condition" может быть передано как другой параметр, если это необходимо.

Я вполне уверен, что это не может быть сделано, как описано. Казалось бы, ваши инженеры могут написать весь код из #ifdef в #endif, и единственные "зацепки", которые у вас есть, - это условные символы и условие. Этого не достаточно Некоторые полуслучайные мысли:

  • Вы можете превратить условие в вызов функции и посчитать, как часто она вызывается.
  • Вы можете требовать определенного "нулевого поведения", когда все условия установлены в "ложь".
  • Вы можете создать функцию, которую ваши инженеры должны вызывать внутри своего блока, чтобы получить доступ к чему-либо, и проверять во время выполнения, чтобы она не вызывалась, если условие ложно.

В конечном счете, я думаю, что вам лучше использовать инструменты анализа исходного кода, чтобы анализировать исходный код и сообщать о нарушениях стиля кодирования. Это может быть CppCheck или один из них: http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis.

Другие вопросы по тегам