2013-02-25 3 views
3

Мне было интересно, как стандартные показатели сложности кода (например, LOC, McCabe cyclomatic complex, Halstead metrics и т. Д.) Вычисляются перед ifdefs в коде C/C++.Метрики сложности кода и ifdefs

Если ifdefs игнорируются, синтаксические ошибки (или даже ошибки типа) могут возникнуть, например, в:

  1. #ifdef FOO
  2. для (I = 0; я < х; я ++) {
  3. #else
  4. для (I = 0; я < у; я ++) {
  5. #endif
  6. Е (...)
  7. }

Если линии 1, 3 и 5, игнорируются, результирующий код будет иметь одну петлю внутри другого, и отсутствующий «}» (таким образом ошибку синтаксиса).

Если учитываются #ifdefs, тогда для каждого варианта потребуется одна результирующая мера (в этом случае одна, когда FOO определена, а другая - для случая, когда FOO не определена). Однако такой подход может легко взорваться на практике.

Глядя на http://manpages.ubuntu.com/manpages/natty/man1/pmccabe.1.html, справочная страница сообщает, что:

Синтаксический pmccabe игнорирует все директивы CPP препроцессора - вычисления сложности появления кода, а не сложности после препроцессора искалечил код. Это особенно важно , поскольку простые вещи, такие как getchar (3), расширяются в макросы, которые увеличивают сложность сложности .

Но, как я уже сказал, такой подход может привести к появлению ошибок кода, что, в свою очередь, может помешать процессу вычисления или привести к некорректному значению.

Как инструменты преодолевают эту проблему (если они вообще преодолеваются)?

С уважением.

ответ

2

Если переписать, что строить, как

#ifdef FOO 
# define LOOPEND x 
#else 
# define LOOPEND y 
#endif 

или что-то подобное, не должно быть никаких проблем.

Если вы не хотите, чтобы сделать это, и ваша сложность проверка не понимает препроцессора, вы можете запустить его на выходе препроцессора, как с FOO определен и с FOO неопределенными, а затем взять максимум из значения, которые он производит, чтобы получить нижнюю границу реальной сложности. С GCC препроцессор вызывается с помощью gcc -E; другие компиляторы будут иметь аналогичный вариант.

(Конечно, если у вас есть много этого колдовства CPP, вы останетесь с экспоненциальным количеством возможностей. Но это цена, которую вы платите за использование препроцессора, то же самое относится и к тестированию.)

+0

Для первой части: как измерить метрики сложности в существующем коде C/C++? Мы говорим о миллионах строк кода, поэтому переписывание не является возможным. Вторая часть: она взрывается, учитывая базу кода со сто макропеременных (2^n, где n обозначает такие макросы) – leco

+0

@LeonardoPassos: зависит. Для чего вам нужны данные о сложности? –

1

Многие из метрических калькуляторов не используют полные или согласованные синтаксические анализаторы, вместо этого они выполняют (может быть) первую пару фаз перевода, а затем ищут ключевые слова.

Поскольку они не рассматривают все проблемы синтаксиса, как вы описываете, не блокируйте их. В любом случае они становятся хрупкими по-другому, на самом деле я видел, что cyclo-2.0 полностью не работает на твердом производственном коде.

0

Я бы подумал, что в более крупном проекте (а не в 20-ти линейном «эксперименте») сумма #ifdef и аналогичные, которые влияют на АКТУАЛЬНУЮ сложность кода, будут минимальными - вы надеетесь, что большинство из этих типы выражений находятся в изолированных единицах, которые слишком сильно не влияют на общий балл.

Но да, если у вас есть небольшой набор кода с большими суммами #ifdef и сложностью в пределах #ifdef частей, вы можете получить ошибку. Ручная проверка кода сможет рассказать вам об этом.

+0

Привет, как указано в приведенном выше комментарии (см. Комментарий для larsmans), ручная работа или комбинаторный вариант не вариант :( – leco

+0

Да, но мое упоминание о ручной работе применимо только для приложений SMALL - если это большой проект, конечно, ваши результаты будут практически одинаковыми! –

Смежные вопросы