Обеспечить проверку состояния перед блоками кода C
Короткая история: я хочу обеспечить проверку условий во время выполнения в определенных условно скомпилированных блоках кода, но не в других.
Длинная история: наша база кода C в значительной степени опирается на профилирование. У нас много разных профилей, и почти каждый модуль имеет #ifdef
s для как минимум 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.