Описание
Встроенное ограничение, которое не уважают, происходит, когда вы обращаетесь к файлу, определяют объем модифицируемой статической переменной или задают локальную модифицируемую статическую переменную в нестатической встроенной функции. Средство проверки рассматривает переменную как модифицируемую, если это не 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;
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;
}
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;
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;
}
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;
}