Каково различие между глобальными помехами и статической энергозависимой переменной?

28
задан Claudio 18 September 2013 в 14:47
поделиться

6 ответов

Они - разные вещи. Я не эксперт в энергозависимой семантике. Но я думаю, что это имеет смысл, что описано здесь.

Глобальный

Глобальный просто означает, что рассматриваемый идентификатор объявляется в объеме файла. Существуют различные объемы, вызванная функция (где goto-маркировки определяются в), п¬Ѓle (где globals находятся), блок (где нормальные локальные переменные находятся), и прототип функции (где параметры функции находятся). Это понятие просто существует для структурирования видимости идентификаторов. Это не имеет никакого отношения к оптимизации.

Статичный

static продолжительность хранения (мы не посмотрим на это здесь), и способ дать имя, объявленное в файле, определяют объем внутренней связи. Это может быть сделано для функций или возражает только требуемый в одной единице перевода. Типичный пример мог бы быть help функция, распечатывающая принятые параметры, и который только называют от main функция, определяемая в том же .c файл.

6.2.2/2 в проекте C99:

, Если объявление п¬Ѓle определяет объем identiп¬Ѓer для объекта или функции, содержит класс памяти speciп¬Ѓer статичный, identiп¬Ѓer имеет внутреннюю связь.

Внутренняя связь означает, что идентификатор не видим вне текущей единицы перевода (как help функция вышеупомянутых).

Энергозависимый

Энергозависимый другая вещь: ( 6.7.3/6)

объект, который имеет энергозависимый-qualiп¬Ѓed тип, может быть modiп¬Ѓed способами, неизвестными реализации, или иметь другие неизвестные побочные эффекты. Поэтому любое выражение, относящееся к такому объекту, должно быть оценено строго согласно правилам абстрактной машины, как описано в 5.1.2.3. Кроме того, в каждой последовательности указывают, что значение, в последний раз сохраненное в объекте, должно согласиться с предписанным абстрактной машиной, за исключением modiп¬Ѓed неизвестными факторами, упомянутыми ранее.

Стандарт предоставляет превосходный пример для примера, где volatile было бы избыточно ( 5.1.2.3/8):

реализация могла бы deп¬Ѓne взаимно-однозначное соответствие между абстрактной и фактической семантикой: в каждой точке последовательности значения фактических объектов согласились бы с теми speciп¬Ѓed абстрактной семантикой. Ключевое слово volatile тогда было бы избыточно.

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

абстрактная семантика - то, что компилятор может вывести из наблюдения только последовательности кода в рамках конкретной программы. Эффекты оптимизации не важны здесь. фактическая семантика включают эффект побочных эффектов, сделанных путем записи в объекты (например, изменения элементов памяти). Квалификация объекта как энергозависимый означает, что тот всегда получает значение объекта прямо из памяти ("как изменено неизвестными факторами"). Стандарт не упоминает потоки нигде, и если необходимо полагаться на порядок изменений, или на атомарности операций, необходимо использовать зависимого платформы способы гарантировать это.

Для легкого для понимания обзора Intel имеет большую статью об этом здесь .

, Что я должен сделать теперь?

Продолжают объявлять Ваш объем файла (глобальные) данные как энергозависимый. Глобальные данные сам по себе не означают, что значение переменных будет равняться значению, сохраненному в памяти. И статичный действительно только делает Ваши объекты локальными для текущей единицы перевода (ток .c файлы и все другие файлы #include'ed им).

21
ответ дан Johannes Schaub - litb 28 November 2019 в 02:31
поделиться

Сначала позвольте мне упомянуть, что статическая глобальная переменная, совпадает с глобальной переменной, за исключением того, что Вы ограничиваете переменную объемом файла. Т.е. Вы не можете использовать эту глобальную переменную в других файлах через extern ключевое слово.

, Таким образом, можно уменьшить вопрос глобальным переменным по сравнению с энергозависимыми переменными.

Теперь на энергозависимый:

Как const, volatile модификатор типа.

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

Объекты, объявленные как volatile, не могут использоваться в определенной оптимизации.

система всегда читает текущее истинное значение энергозависимого объекта в точке, это используется, даже если предыдущая инструкция, которую попросили значения от того же объекта. Кроме того, значение объекта сразу записано на присвоении. Это означает, что нет никакого кэширования энергозависимой переменной в регистр ЦП.

у доктора Jobb есть большая статья об энергозависимом .

Вот пример от статьи доктора Jobb:

class Gadget
{
public:
    void Wait()
    {
        while (!flag_)
        {
            Sleep(1000); // sleeps for 1000 milliseconds
        }
    }
    void Wakeup()
    {
        flag_ = true;
    }
    ...
private:
    bool flag_;
};

, Если компилятор видит, что Sleep() внешний вызов, он предположит, что Sleep() не может возможно изменить переменное значение _ флага. Таким образом, компилятор может сохранить значение flag_ в регистре. И в этом случае, это никогда не будет изменяться. Но если другое пробуждение вызовов потока, первый поток все еще читает из регистра ЦП. Wait() никогда не будет пробуждение.

Итак, почему не только никогда переменные кэша в регистры и не избегают проблемы полностью? Оказывается, что эта оптимизация может действительно сохранить Вас много времени в целом. Таким образом, C/C++ позволяет Вам явно отключать его через volatile ключевое слово.

факт выше того flag_ был членской переменной, и не глобальной переменной (ни статичный глобальный) не имеет значения. Объяснение после примера дает корректное обоснование, даже если Вы имеете дело с глобальными переменными (и статическими глобальными переменными).

распространенное заблуждение А - то, что объявление переменной volatile достаточно для обеспечения потокобезопасности. Операции на переменной все еще не являются атомарными, даже при том, что они не "кэшируются" в регистрах

энергозависимый с указателями:

Энергозависимый с указателями, работами как константа с указателями.

переменная А типа volatile int * означает, что переменная, на которую указывает указатель, энергозависима.

переменная А типа int * volatile означает, что сам указатель энергозависим.

43
ответ дан Toby 28 November 2019 в 02:31
поделиться

"Энергозависимое" ключевое слово предлагает, чтобы компилятор не сделал определенную оптимизацию на коде, включающем ту переменную; если Вы просто используете глобальную переменную, ничто не предотвращает компилятор для неправильной оптимизации кода.

Пример:

#define MYPORT 0xDEADB33F

volatile char *portptr = (char*)MYPORT;
*portptr = 'A';
*portptr = 'B';

Без "энергозависимого", первая запись может быть оптимизирована.

14
ответ дан Adam Rosenfield 28 November 2019 в 02:31
поделиться

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

Энергозависимая переменная на Википедию

4
ответ дан Krunch 28 November 2019 в 02:31
поделиться

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

  • Различные аппаратные средства (больше процессоров, различной архитектуры памяти)
  • А новая версия компилятора с лучшей оптимизацией.
  • Случайное изменение в синхронизации между потоками. Проблема может только произойти одно время в 10 миллионах.
  • Различные настройки компиляторной оптимизации.

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

, Конечно, если Ваша программа не является многопоточной тогда, она не имеет значения.

3
ответ дан Darron 28 November 2019 в 02:31
поделиться

Я ответ +1 Фриоля. Я хотел бы добавить некоторую точность, поскольку, кажется, существует много беспорядков в различных ответах: энергозависимый C не является энергозависимым Java.

Поэтому сначала, компиляторы могут сделать, большая оптимизация на на основе потока данных Вашей программы, энергозависимой в C, предотвращает это, это удостоверяется Вы действительно загрузка и хранение к местоположению каждый раз (вместо того, чтобы использовать регистры вытирания его, например). Полезно, когда у Вас есть порт IO с отображенной памятью, как указал Фриоль.

Энергозависимый в C не имеет никакого отношения к аппаратным кэшам или многопоточности. Это не вставляет заборы памяти, и у Вас нет абсолютно никакого garanty на порядке операций, если два потока делают доступы к нему. Энергозависимое ключевое слово Java делает точно что хотя: вставка заборов памяти при необходимости.

3
ответ дан Piotr Lesnicki 28 November 2019 в 02:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: