Инициализация
От: Alexander G Украина  
Дата: 20.12.13 09:11
Оценка: +2 -2
Ну вот какого хрена в век, когда лямбды уже не вызывают "это ты выпендрился?"-реакцию на код ревью, когда все самые необходимые смарт-поинтеры уже есть в std, а в boost есть вообще все нужные, до сих пор можно наткнуться на непредсказуемую инициализацию переменных?

int count;
RegQueryValue(count); // забыли проверить возвращаемое значение
for (int i = 0 ; i < count ; i++) // и приплыли - цикл повторяется непредсказуемое количество раз



Почему не введут инициализацию для всех простых типов?

Для маньяков, которые не желают "платить за то, что не используют", можно же ввести синтаксис для "старой доброй русской рулетки".
Варианты, как это можно сделать:

int i = uninitialized;  // "uninitialized" - не спец. значение, а magic, работающий только в инициализаторах, означающий, что мы хотим адреналина

int i = void;  // мы даже можем не вводить новый кейворд, если это так важно

[[uninitialized]]
int i; // придумали аттрибуты, значит почему бы не использовать


Может, это можно протянуть как пропозл?
Русский военный корабль идёт ко дну!
Re: Инициализация
От: skeptic  
Дата: 20.12.13 09:18
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Почему не введут инициализацию для всех простых типов?


Обратная совместимость + увеличится объём кода.
В силу того что компилятор выдаёт предупреждения по поводу неинициализированных переменных,
никому спец синтаксис для этого не нужен.

AG>Может, это можно протянуть как пропозл?


Можно попробовать, но вряд ли.
Re: Инициализация
От: Vzhyk  
Дата: 20.12.13 09:22
Оценка: +4
12/20/2013 12:11 PM, Alexander G пишет:

> Почему не введут инициализацию для всех простых типов?

Потому что тупую голову и кривые руки инструментом не поправишь.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: Инициализация
От: skeptic  
Дата: 20.12.13 09:24
Оценка:
Здравствуйте, Vzhyk, Вы писали:

V>12/20/2013 12:11 PM, Alexander G пишет:


>> Почему не введут инициализацию для всех простых типов?

V>Потому что тупую голову и кривые руки инструментом не поправишь.

Как то слишком уж радикально ты...
Re[2]: Инициализация
От: Alexander G Украина  
Дата: 20.12.13 09:39
Оценка:
Здравствуйте, skeptic, Вы писали:

S>Обратная совместимость


С чем? Кто-то рассчитывает прочитать определённый мусор?

S> + увеличится объём кода.


Чтобы пофиксить local static variables, сделав их потокобезопасными, на это пошли.

Вообще, в большинстве случаев переменные явно инициализированы в месте объеявления.
Если чуть позже места объявления — можно соптимизировать.
Если вообще не инициализированы, но использованы — это, скорее всего, та самая ошибка.

S>В силу того что компилятор выдаёт предупреждения по поводу неинициализированных переменных,

S>никому спец синтаксис для этого не нужен.

студия спокойно глотает с /W4 и даже /WAll


inline void f(int&) {}

int main()
{
    int i;
    f(i);
    return i;
}
Русский военный корабль идёт ко дну!
Re[3]: Инициализация
От: skeptic  
Дата: 20.12.13 09:44
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, skeptic, Вы писали:


S>>Обратная совместимость


AG>С чем? Кто-то рассчитывает прочитать определённый мусор?


Ну, если я тебя правильно понял, то ты хочешь что бы переменную нельзя было объявить без определения, так?
Ну в таком случае у тебя куча уже написанного кода перестанет работать.
Re[4]: Инициализация
От: Alexander G Украина  
Дата: 20.12.13 09:46
Оценка:
Здравствуйте, skeptic, Вы писали:


S>Ну, если я тебя правильно понял, то ты хочешь что бы переменную нельзя было объявить без определения, так?

S>Ну в таком случае у тебя куча уже написанного кода перестанет работать.

Нет, я хочу, чтобы просто

int i;

компилилось как

int i = 0;


а если не нужен этот "= 0", то синтаксис, как выше.
Русский военный корабль идёт ко дну!
Re[5]: Инициализация
От: skeptic  
Дата: 20.12.13 09:50
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, skeptic, Вы писали:



S>>Ну, если я тебя правильно понял, то ты хочешь что бы переменную нельзя было объявить без определения, так?

S>>Ну в таком случае у тебя куча уже написанного кода перестанет работать.

AG>Нет, я хочу, чтобы просто


AG>
AG>int i;

AG>

AG>компилилось как

AG>
AG>int i = 0;

AG>


AG>а если не нужен этот "= 0", то синтаксис, как выше.


А что такое — "= 0"? и для любого ли типа такой 0 прокатит?
Ну и в конце концов чем отличается такой вот 0 от мусора?
Re[6]: Инициализация
От: Alexander G Украина  
Дата: 20.12.13 09:54
Оценка:
Здравствуйте, skeptic, Вы писали:

S>А что такое — "= 0"? и для любого ли типа такой 0 прокатит?


Дефолтная инициализация.
У любого типа есть она.

Вот такое дефолтно инициализирует структуру, содержащую любые поля.
struct {
  int i;
  void* p;
} s = {};


S>Ну и в конце концов чем отличается такой вот 0 от мусора?


Предсказуемостью. Меньше будет проблем которые воспроизводятся только в определённой фазе луны.
Русский военный корабль идёт ко дну!
Re[7]: Инициализация
От: skeptic  
Дата: 20.12.13 10:02
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, skeptic, Вы писали:


S>>Ну и в конце концов чем отличается такой вот 0 от мусора?


AG>Предсказуемостью. Меньше будет проблем которые воспроизводятся только в определённой фазе луны.

Какой предсказуемостью? Как ты узнаешь что 0 это неинициализированная переменная а не кто то присвоил 0?
Re[8]: Инициализация
От: Alexander G Украина  
Дата: 20.12.13 10:13
Оценка: +1
Здравствуйте, skeptic, Вы писали:

S>Какой предсказуемостью? Как ты узнаешь что 0 это неинициализированная переменная а не кто то присвоил 0?


С реализацией такого предложения будет не важно, присвоил ли кто-то 0, или оно там само.

Предсказуемость в том, что даже если 0 там не есть то, что хотели, ошибочное поведение будет стабильным, а не зависеть от конфигурации, компилятора, ОС, и того, какая функция вызывалась на этом стеке раньше.
Русский военный корабль идёт ко дну!
Re: Инициализация
От: B0FEE664  
Дата: 20.12.13 10:17
Оценка: 6 (1) +2 -1
Здравствуйте, Alexander G, Вы писали:

AG>Ну вот какого хрена в век, когда лямбды уже не вызывают "это ты выпендрился?"-реакцию на код ревью, когда все самые необходимые смарт-поинтеры уже есть в std, а в boost есть вообще все нужные, до сих пор можно наткнуться на непредсказуемую инициализацию переменных?

Потому, что массивы бывают длинны.

AG>
AG>int count;
AG>RegQueryValue(count); // забыли проверить возвращаемое значение
AG>for (int i = 0 ; i < count ; i++) // и приплыли - цикл повторяется непредсказуемое количество раз
AG>

А что собственно вы тут собрались проверять?

AG>Почему не введут инициализацию для всех простых типов?

А зачем она нужна? Если вы про приведённый пример, то хочется спросить, почему он не записан так:
  const int count = RegQueryValue();
  for (int i = 0 ; i < count ; i++)


AG>Для маньяков, которые не желают "платить за то, что не используют", можно же ввести синтаксис для "старой доброй русской рулетки".

Обратная совместимость важнее удобства.

AG>Может, это можно протянуть как пропозл?

Я против.
И каждый день — без права на ошибку...
Re[3]: Инициализация
От: Vzhyk  
Дата: 20.12.13 10:21
Оценка: +5 :)
12/20/2013 12:24 PM, skeptic пишет:

> Как то слишком уж радикально ты...

Просто надоело быть толерантным здесь. Как не почитаешь идеи по С++
здесь, так за голову хватаешься, страшно становится.
Причем 90% обсуждений в 2 стилях, а как мне забомбить вот такую странную
нетривиальную фигню в коде (шоб никто не догадался) и ой, а чей-то у
меня память течет, нет ли доктора-телепата.
Posted via RSDN NNTP Server 2.1 beta
Re[9]: Инициализация
От: skeptic  
Дата: 20.12.13 10:27
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Здравствуйте, skeptic, Вы писали:


S>>Какой предсказуемостью? Как ты узнаешь что 0 это неинициализированная переменная а не кто то присвоил 0?


AG>С реализацией такого предложения будет не важно, присвоил ли кто-то 0, или оно там само.


AG>Предсказуемость в том, что даже если 0 там не есть то, что хотели, ошибочное поведение будет стабильным, а не зависеть от конфигурации, компилятора, ОС, и того, какая функция вызывалась на этом стеке раньше.


Ну, по спец.синтаксису я резко против, по понятным причинам — поломается много кода.
А по дефолтному присваиванию я думаю это не решит проблемы, зато добавит их разработчикам стандарта и компиляторов.
Ну и всё таки не ясно как выбирать дефолтные значения для разных типов?
Re[10]: Инициализация
От: Alexander G Украина  
Дата: 20.12.13 10:34
Оценка:
Здравствуйте, skeptic, Вы писали:

S>Ну и всё таки не ясно как выбирать дефолтные значения для разных типов?


Они уже давно выбраны.
Я привёл выше синтаксис как до них добраться, вот другой синтаксис:
template<class T>
void InitializeDefault()
{
   T t = T(); // для чисел - 0, для bool - false, для указателей - nullptr, для классов - дефолтный конструктор.
  // на большинстве платформ двоичное представление этих значений - все байты нули.
}
Русский военный корабль идёт ко дну!
Re[9]: Инициализация
От: uzhas Ниоткуда  
Дата: 20.12.13 10:35
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Предсказуемость в том, что даже если 0 там не есть то, что хотели, ошибочное поведение будет стабильным, а не зависеть от конфигурации, компилятора, ОС, и того, какая функция вызывалась на этом стеке раньше.


в целом согласен, что пока мы в прошлом веке, т.к. спотыкаемся о подобные проблемы. рандомные баги из-за неинициализированных данных очень неприятны. хочется, чтобы программы вели себя детерминировано и баги можно было легко воспроизводить
проблему можно частично решать не на уровне языка, а на уровне средств : компиляторы должны выявлять такие моменты и очень часто это довольно простой код (члены класса в конструкторе не инициализируются, переменные на стеке)
Re: Инициализация
От: Кодт Россия  
Дата: 20.12.13 10:36
Оценка: 6 (2) +2 -1
Здравствуйте, Alexander G, Вы писали:

AG>Ну вот какого хрена в век, когда лямбды уже не вызывают "это ты выпендрился?"-реакцию на код ревью, когда все самые необходимые смарт-поинтеры уже есть в std, а в boost есть вообще все нужные, до сих пор можно наткнуться на непредсказуемую инициализацию переменных?


Потому что функция в случае неудачи может
— не инициализировать
— инициализировать удобным дефолтным или сигнальным значением (0)
— инициализировать неудобным сигнальным значением (-1 или 0xFFFFFFFF, или 0xDEADFACE какое-нибудь)
— инициализировать случайным мусором

Выход из этого — протаскивание в API самонесущих типов — boost::optional, например. Только это очень недружественно для FFI.

AG>Почему не введут инициализацию для всех простых типов?

AG>Для маньяков, которые не желают "платить за то, что не используют", можно же ввести синтаксис для "старой доброй русской рулетки".

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

AG>Может, это можно протянуть как пропозл?


Идея прикольная, но может оказаться достаточно дорогой.
Лучше уж ввести какую-нибудь прагму #pragma zeroinit, которая форсировала бы инициализацию всех переменных подряд.
Перекуём баги на фичи!
Re[2]: Инициализация
От: Alexander G Украина  
Дата: 20.12.13 10:44
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Потому, что массивы бывают длинны.


Принимается.
Хотя я предложил и варианты эскейпа для явной не-инициализации, которые можно применить и к массивам.

int a[1000] = { void };

[[uninitialized]]
int a[1000];


AG>>RegQueryValue(count); // забыли проверить возвращаемое значение


BFE>А что собственно вы тут собрались проверять?


Это функция некоторого system API или legacy API, сообщающая результат через код возврата, который надо было бы проверить.

BFE>Обратная совместимость важнее удобства.


Компиляция старого кода не ломается же.
Да, перформанс инициализации массивов ломается в некоторых случаях.
Русский военный корабль идёт ко дну!
Re: Инициализация
От: Mr.Delphist  
Дата: 20.12.13 10:44
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Ну вот какого хрена в век, когда лямбды уже не вызывают "это ты выпендрился?"-реакцию на код ревью, когда все самые необходимые смарт-поинтеры уже есть в std, а в boost есть вообще все нужные, до сих пор можно наткнуться на непредсказуемую инициализацию переменных?


AG>
AG>int count;
AG>RegQueryValue(count); // забыли проверить возвращаемое значение
AG>for (int i = 0 ; i < count ; i++) // и приплыли - цикл повторяется непредсказуемое количество раз
AG>


Найдите 10 отличий:
int count;
if (ERROR_SUCCESS != RegQueryValue(count)) // не забыли проверить возвращаемое значение
    break; // return, continue, throw, etc - короче, включаем мозги по ситуации
for (int i = 0 ; i < count ; i++) // и не приплыли - цикл повторяется предсказуемое количество раз
Re[9]: Инициализация
От: Evgeny.Panasyuk Россия  
Дата: 20.12.13 10:46
Оценка: 1 (1)
Здравствуйте, Alexander G, Вы писали:

S>>Какой предсказуемостью? Как ты узнаешь что 0 это неинициализированная переменная а не кто то присвоил 0?

AG>С реализацией такого предложения будет не важно, присвоил ли кто-то 0, или оно там само.
AG>Предсказуемость в том, что даже если 0 там не есть то, что хотели, ошибочное поведение будет стабильным, а не зависеть от конфигурации, компилятора, ОС, и того, какая функция вызывалась на этом стеке раньше.

Я бы предпочёл нестабильное поведение на ошибочном коде — пусть ошибки дают о себе знать как можно раньше. valgrind или какой-нибудь sanitazer прикрученный к юнит или интеграционным тестам, поймал бы это (+ другие классы ошибок).
А то так и до two's complement int недалеко

Вот даже в твоём коде:
int count;
RegQueryValue(count);
for (int i = 0 ; i < count ; i++) // ладно, был бы ноль - был бы noop
    ;
// А тут-то что делать? RegQueryValue ведь вернул ошибку
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.