ПроблемаВстроенное ограничение, которое не уважают, происходит, когда вы обращаетесь к файлу, определяют объем модифицируемой статической переменной или задают локальную модифицируемую статическую переменную в нестатической встроенной функции. Средство проверки рассматривает переменную как модифицируемую, если это не const
- квалифицированный.
Например, var
модифицируемый static
переменная задана в inline
функциональный func
. g_step
модифицируемая статическая переменная осциллографа файла, упомянутая в той же встроенной функции.
static int g_step;
inline void func (void) {
static int var = 0;
var += g_step;
}
РискКогда вы измените статическую переменную в нескольких вызовах функции, вы ожидаете изменять ту же переменную в каждом вызове. Например, каждый раз вы вызываете func
, тот же экземпляр var1
постепенно увеличивается, но отдельный экземпляр var2
постепенно увеличивается.
void func(void) {
static var1 = 0;
var2 = 0;
var1++;
var2++;
}
Если функция имеет встроенный и невстроенное определение в отдельных файлах, когда вы вызываете функцию, стандарт C позволяет компиляторам использовать или встроенный или невстроенную форму (см. ISO®/IEC 9899:2011, секунда. 6.7.4). Если ваш компилятор использует встроенное определение в одном вызове и невстроенное определение в другом, вы больше не изменяете ту же переменную в обоих вызовах. Это поведение игнорирует ожидания от статической переменной.
ФиксацияИспользуйте одни из этих мер:
Если вы не намереваетесь изменить переменную, объявите его как const
.
Если вы не изменяете переменную, нет никакого вопроса неожиданной модификации.
Сделайте переменную non-static
. Удалите static
спецификатор от объявления.
Если переменная задана в функции, это становится регулярной локальной переменной. Если задано в осциллографе файла, это становится переменной экстерна. Убедитесь, что это изменение в поведении - то, что вы предназначаете.
Сделайте функциональный static
. Добавьте static
спецификатор к функциональному определению.
Если вы делаете функциональный static
, файл со встроенным определением использует встроенное определение, когда функция вызвана. Другие файлы используют другое определение функции. Компилятор не решает, какое функциональное определение используется.
Пример - использование статической переменной во встроенном и внешнем определении/* file1. c : contains inline definition of get_random()*/
inline unsigned int get_random(void)
{
static unsigned int m_z = 0xdeadbeef; //Noncompliant
static unsigned int m_w = 0xbaddecaf; //Noncompliant
/* Compute next pseudorandom value and update seeds */
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
int call_get_random(void)
{
unsigned int rand_no;
int ii;
for (ii = 0; ii < 100; ii++) {
rand_no = get_random();
}
rand_no = get_random();
return 0;
}
/* file2. c : contains external definition of get_random()*/
extern unsigned int get_random(void)
{
/* Initialize seeds */
static unsigned int m_z = 0xdeadbeef;
static unsigned int m_w = 0xbaddecaf;
/* Compute next pseudorandom value and update seeds */
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
В этом примере, get_random()
имеет встроенное определение в file1.c
и внешнее определение в file2.c
. Когда get_random
называется в file1.c
, компиляторы могут, чтобы выбрать, использовать ли встроенное или внешнее определение.
В зависимости от используемого определения вы можете или не можете изменить версию m_z
и m_w
во встроенной версии get_random()
. Это поведение противоречит обычным ожиданиям от статической переменной. Когда вы вызываете get_random()
, вы ожидаете изменять тот же m_z
и m_w
.
Коррекция — делает встроенные функциональные помехиОдна возможная коррекция должна сделать встроенный get_random()
статический. Независимо от вашего компилятора, вызовов get_random()
в file1.c
затем используйте встроенное определение. Вызовы get_random()
в других файлах используют внешнее определение. Эта фиксация удаляет неоднозначность, о которой используется определение и изменяются ли статические переменные в том определении.
/* file1. c : contains inline definition of get_random()*/
static inline unsigned int get_random(void)
{
static unsigned int m_z = 0xdeadbeef; //Compliant
static unsigned int m_w = 0xbaddecaf; //Compliant
/* Compute next pseudorandom value and update seeds */
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
int call_get_random(void)
{
unsigned int rand_no;
int ii;
for (ii = 0; ii < 100; ii++) {
rand_no = get_random();
}
rand_no = get_random();
return 0;
}
/* file2. c : contains external definition of get_random()*/
extern unsigned int get_random(void)
{
/* Initialize seeds */
static unsigned int m_z = 0xdeadbeef;
static unsigned int m_w = 0xbaddecaf;
/* Compute next pseudorandom value and update seeds */
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}