реклама на сайте
подробности

 
 
> Использование static переменных
777777
сообщение Oct 7 2010, 15:41
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(Сергей Борщ @ Oct 7 2010, 00:09)
Оптимизатор вполне может выкинуть запись в любую переменную, будь то обычный int или массив, если он видит, что результат такой записи не используется (а с его точки зрения он не используется).


Насчет любой переменной вы погорячились - значения static переменных сохраняются даже после выхода из функции и будут иметь его при повторном входе в эту функцию.
Go to the top of the page
 
+Quote Post
3 страниц V  < 1 2 3  
Start new topic
Ответов (30 - 40)
777777
сообщение Oct 11 2010, 07:36
Сообщение #31


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(GetSmart @ Oct 11 2010, 08:41) *
Статик просто размещает переменную в каком-то там сегменте (bss или др.). И всё. Остальное на совести компилятора.

Что именно "всё остальное"? Стандарт четко определяет время жизни (lifetime) переменной. Что по-вашему означает этот термин?

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

Вы даете компилятору слишком много воли. Если бы это было так, то программы было бы невозможно писать. Наслушавшись таких разговоров некоторые предпочитают асм, думая, что компилятор действительно может сгенерировать не то, что написал программист. Но к счастью это не так.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Oct 11 2010, 07:55
Сообщение #32


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Я уже потерял суть спора. Чё не нравится? В смысле, что компилятор (и какой?) сделал не так, как хотелось?

Цитата(777777 @ Oct 11 2010, 12:36) *
Что именно "всё остальное"? Стандарт четко определяет время жизни (lifetime) переменной. Что по-вашему означает этот термин?

В сегменте bss эта переменная будет жить вечно. Довольны?
Вопрос только в том, выкинет ли компилятор какое-нибудь присваивание в эту переменную.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 11 2010, 08:10
Сообщение #33


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(rezident @ Oct 8 2010, 17:54) *
Не его (компилятора) собачье дело! smile.gif Пускай warning выдаст, а я уж сам решу нужна мне там переменная или не нужна. Насчет выбрасывания неиспользуемых функций - согласен, а вот насчет выбрасывания переменных типа static ...ммм... можно привести реальные примеры такого поведения с указанием конкретных компиляторов и параметров оптимизации?

Это уж как вы ему (компилятору) укажете. Выбрасывать-не выбрасывать, предупреждать-не отвлекать на всякую ботву и тд.
По крайней мере GCC так работает.
ключ -fdata-sections позволяет выкидывать неиспользуемые секции данных.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 11 2010, 08:58
Сообщение #34


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(777777 @ Oct 11 2010, 08:30) *
А для чего же он создан? Приведите раздел стандарта который это объясняет. В крайнем случае, приведите пример программы с набором опций компилятора и линкера. Вы ничего этого не сделали...

Для себя я уже давно всё сделал, а Вам народ неоднократно писал про это:
Код
CFLAGS += --combine
CFLAGS += -fwhole-program
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections

С такими опциями со статической переменной может быть вообще всё что угодно
(всё будет сильно зависеть от контекста Вашей программы).


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 11 2010, 10:20
Сообщение #35


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(demiurg_spb @ Oct 11 2010, 12:58) *
Для себя я уже давно всё сделал, а Вам народ неоднократно писал про это:
Код
CFLAGS += --combine
CFLAGS += -fwhole-program
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections

С такими опциями со статической переменной может быть вообще всё что угодно

Ну что ж, попробуем тупо воткнуть их в проект
Код
int main()
{
    foo();
}

volatile int volatile * p_a;

void foo (void)
{
    static int a;

    p_a = &a;
    a = 2;
    a = 3;
}

Получаем на выходе:
Код
void foo (void)
{
    static int a;

    p_a = &a;
  56:    80 e0           ldi    r24, 0x00; 0
  58:    91 e0           ldi    r25, 0x01; 1
  5a:    90 93 03 01     sts    0x0103, r25
  5e:    80 93 02 01     sts    0x0102, r24
    a = 2;
    a = 3;
  62:    83 e0           ldi    r24, 0x03; 3
  64:    90 e0           ldi    r25, 0x00; 0
  66:    90 93 01 01     sts    0x0101, r25
  6a:    80 93 00 01     sts    0x0100, r24

Если между присваиваниями воткнуть обращение к какой-нибудь функции (даже к ней самой), то он и первое присваивание не выкинет:
Код
void foo (void)
{
    static int a;

    p_a = &a;
  7e:    80 e0           ldi    r24, 0x00; 0
  80:    91 e0           ldi    r25, 0x01; 1
  82:    90 93 03 01     sts    0x0103, r25
  86:    80 93 02 01     sts    0x0102, r24
    a = 2;
  8a:    82 e0           ldi    r24, 0x02; 2
  8c:    90 e0           ldi    r25, 0x00; 0
  8e:    90 93 01 01     sts    0x0101, r25
  92:    80 93 00 01     sts    0x0100, r24
    foo();
  96:    df df           rcall    .-66     ; 0x56 <foo>
    a = 3;
  98:    83 e0           ldi    r24, 0x03; 3
  9a:    90 e0           ldi    r25, 0x00; 0
  9c:    90 93 01 01     sts    0x0101, r25
  a0:    80 93 00 01     sts    0x0100, r24

Цитата(demiurg_spb @ Oct 11 2010, 12:58) *
(всё будет сильно зависеть от контекста Вашей программы).

Ну, если например в ней не будет обращений к foo, то он ее выкинет, это отследить не сложно. Но если обращение есть, то никакой самодеятельности не будет. (Если только там нет ключей, заставляющих его нарушать стандарт, но я сомневаюсь и наличии таковых)
Go to the top of the page
 
+Quote Post
halfdoom
сообщение Oct 11 2010, 10:52
Сообщение #36


Профессионал
*****

Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072



Цитата(777777 @ Oct 11 2010, 07:30) *
Статик создан именно для того, чтобы его значение, установленное в функции, сохранялось при выходе из нее и было таким же при повторном входе в эту функцию.

Оригинально. Вообще ключевое слово 'static' определяет область видимости переменной, а в контексте функции к этому добавляется требование ее размещения в области данных, а не стека. Вот и все. Больше компилятор ничего не ограничивает, и если он достаточно умный, то найдя только присваивания данной переменной без передачи (или возврата) ее адреса в другие функции имеет полное право оптимизировать использование этой переменной, вплоть до полного исключения ее из результата компиляции.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Oct 11 2010, 10:58
Сообщение #37


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(halfdoom @ Oct 11 2010, 15:52) *
Оригинально. Вообще ключевое слово 'static' определяет область видимости переменной, а в контексте функции к этому добавляется требование ее размещения в области данных, а не стека.

...переменной <==> функции...


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
777777
сообщение Oct 11 2010, 11:10
Сообщение #38


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(halfdoom @ Oct 11 2010, 14:52) *
Оригинально. Вообще ключевое слово 'static' определяет область видимости переменной, а в контексте функции к этому добавляется требование ее размещения в области данных, а не стека. Вот и все. Больше компилятор ничего не ограничивает, и если он достаточно умный, то найдя только присваивания данной переменной без передачи (или возврата) ее адреса в другие функции имеет полное право оптимизировать использование этой переменной, вплоть до полного исключения ее из результата компиляции.

Ключевое слово - lifetime. У static переменной оно бесконечное. Поэтому наличие только присваивания не может служить основанием для того чтобы заявлять о ее неиспользовании. Она может понадобиться при следующем вызове функции.

И вообще, если компилятор выкидывает какую-то переменную или часть кода, то это означает что и без оптимизаций эта переменная/код не будет использована. Поэтому не стоит так бояться "самодеятельности" компилятора, если таковая обнаружится, не спешите выключать оптимизацию, лучше повнимательнее посмотрите исходник.


Цитата(GetSmart @ Oct 11 2010, 14:58) *
...переменной <==> функции...

С самого начала речь шла о static переменных в контексте функций.
Go to the top of the page
 
+Quote Post
halfdoom
сообщение Oct 11 2010, 11:18
Сообщение #39


Профессионал
*****

Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072



Цитата(777777 @ Oct 11 2010, 14:10) *
Ключевое слово - lifetime. У static переменной оно бесконечное. Поэтому наличие только присваивания не может служить основанием для того чтобы заявлять о ее неиспользовании. Она может понадобиться при следующем вызове функции.

Современные методы анализа потока данных и кода позволяют выяснить, что в конструкциях типа приведенной ниже, ни при первом, ни при последующем вызовах необходимости в выделении места под переменную нет.
Код
int
test(int aa)
{
  static int bb = 5;

  bb = 3;
  bb = 2;
  return aa * bb; /* это будет заменено на aa * 2, с последующим удалением bb */
}


В случае с исходником из поста 35, компилятор все делает правильно, т.к. имеется использование адреса переменной вне функции.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Oct 11 2010, 11:25
Сообщение #40


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(777777 @ Oct 11 2010, 16:10) *
... Поэтому наличие только присваивания не может служить основанием для того чтобы заявлять о ее неиспользовании. Она может понадобиться при следующем вызове функции.

Отсутствие её чтения - может. Этот факт анализируют (почти) все современные компиляторы. Могут выдавать ремарку или варнинг. Особенно на "статик" (не глобальную/межмодульную). Шипко умные могут даже выкинуть её, если она не волатильная.

Цитата(777777 @ Oct 11 2010, 15:20) *
Ну, если например в ней не будет обращений к foo, то он ее выкинет, это отследить не сложно. Но если обращение есть, то никакой самодеятельности не будет.

Следите за ходом мысли.
Если foo() сделать статиком, то она рискует быть удалённой, если внутри модуля она на вызывается и адрес её не используется. Даже на 99% она будет удалена современными компиляторами.
То же самое относится и к статик переменным. Если внутри функции (аналог модуля для статик функции) переменная не читается, то не важно есть ли в неё запись, она может быть удалена. Если её адрес используется/записывается в другую переменную, то идёт рекурсия по анализу использования этой второй переменной. Если она не читается, а только прописывается, то сперва удаляется эта вторая переменная, а потом удаляется первая переменная, которая "статик". Всё по-чесноку.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 11 2010, 12:49
Сообщение #41


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(777777 @ Oct 11 2010, 14:20) *
Ну, если например в ней не будет обращений к foo, то он ее выкинет, это отследить не сложно. Но если обращение есть, то никакой самодеятельности не будет. (Если только там нет ключей, заставляющих его нарушать стандарт, но я сомневаюсь и наличии таковых)
Как уже говорили, при использовании ключей combine и fwhole-program, все функции становятся static.
И в этом случае у компилятора руки развязываются полностью.
А со всеми ключикамии для линкера возможно получить кумулятивный эффект, под кодовым названием "без говNа":)
И тут единственное, что может сохранить обращения к переменной это volatile и ничто более.
Повтарюсь, не стоит сюда притягивать за уши static.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 17:02
Рейтинг@Mail.ru


Страница сгенерированна за 0.01478 секунд с 7
ELECTRONIX ©2004-2016