Ошибки, баги, вопросы - страница 2725

 
Vict:

Вы думаете что ваш шарп появился в чистом поле? Корни в Си, структура - это тупо контейнер без лишнего сахара.

Ну а человек произошёл от обезьяны. Но это ведь не значит, что человек - это тупо обезьяна "без лишнего сахара", не так ли? )   Я уже объяснил, что фактически структуры MQL = структуры C#,  за небольшим отличием: в C# они ещё могут имплементировать интерфейсы.  Интерфейсы, Карл! )

Да откуда такая уверенность? Вызов функции из другой единицы трансляции/другого модуля/циклы/компилятор не в духе/... . Не переоценивайте возможности оптимизатора. Это не Copy elision оптимизация, которую обязали делать компиляторы. Если оптимизаторы станут столь умны и это перестанет что-то стоить, то в очередно Cи стандарте пропишут: "дефолтная инициализации не оставляет объект в неопределённом состояни".

Потому что это самая банальная и примитивная вещь, которую даже оптимизацией то назвать сложно.  Думаю, все компиляторы даже в Дебаг-режиме делают это по умолчанию.  Что может быть проще то?  В процессе разбора кода отслеживать доступ к переменным. Если идёт повторная операция на запись и не было операции чтения, то вырезать предыдущую запись.

Вы можете игнорить это, но тогда не удивляйтесь, что приличные кодеры будут смотреть на вас как на говнокодера, когда увидят ваши фаршированные функциями структуры

Я бы скорее ваш подход с работой без инициализации назвал говнокодингом.  Каким главным качеством должна обладать компьютерная программа?  Стабильностью.  При одних и тех же входных данных она должна давать неизменные результаты.  А вы предлагаете класть на это.  Где-то забыл проинициализировать переменную, где-то добавил новое поле в структуру, которое стало неинициализированным во всей программе, и понеслось. Программа работает то так, то эдак...

Язык C создавался в далёкие времена, когда возможности железа были крайне слабые, поэтому значительная часть работы по оптимизации перекладывалась на программиста. А сейчас этот мазохизм уже мало актуален.  Если же вам так прям чешется, то почему вы ссылаетесь на С, а не на ассемблер например?  Кодируйте торговые системы сразу на ассемблере.  Уверен, они станут самыми быстрыми, возможно даже опередят рынок )

 
Alexey Navoykov:

Потому что это самая банальная и примитивная вещь, которую даже оптимизацией то назвать сложно.  Думаю, все компиляторы даже в Дебаг-режиме делают это по умолчанию.  Что может быть проще то?  В процессе разбора кода отслеживать доступ к переменным. Если идёт повторная операция на запись и не было операции чтения, то вырезать предыдущую запись.

Если программа была бы полностью предсказуема при compile time, то её бы вообще не надо было выполнять в run time. Она по определению должна взять что-то из внешнего мира и на основе этого выдать результат, а это неопределённость, которая мешает оптимизатору. Ещё открою тайну - с екзешником в ран тайме линкуются разделяемые библиотеки, оптимизатор ничего не может там отследить. Можно ещё накидать миллион всяких кейсов. Миллион, Карл!)

Где-то забыл проинициализировать переменную, где-то добавил новое поле в структуру, которое стало неинициализированным во всей программе, и понеслось. Программа работает то так, то эдак...

Где-то умножил на 2 вместо 3, вызвал fn() вместо fn_(), ... . Если руки кривые, то беда.

Язык C создавался в далёкие времена, когда возможности железа были крайне слабые, поэтому значительная часть работы по оптимизации перекладывалась на программиста. А сейчас этот мазохизм уже мало актуален.  Если же вам так прям чешется, то почему вы ссылаетесь на С, а не на ассемблер например?  Кодируйте торговые системы сразу на ассемблере.  Уверен, они станут самыми быстрыми, возможно даже опередят рынок )

для справки: стандарты Си (последние, это не C++ стандарты): С11, С18, готовится C2x. Скорее вы написали это в результате некомпетентности.
 
Vict:

Если программа была бы полностью предсказуема при compile time, то её бы вообще не надо было выполнять в run time. Она по определению должна взять что-то из внешнего мира и на основе этого выдать результат, а это неопределённость, которая мешает оптимизатору. Ещё открою тайну - с екзешником в ран тайме линкуются разделяемые библиотеки, оптимизатор ничего не может там отследить. Можно ещё накидать миллион всяких кейсов. Миллион, Карл!)

Обмен данных с внешним миром - это уже частные случаи.  И для них нужны особые решения.  А мы говорим о программировании как таковом, и о тех случаях, где компилятор гарантированно знает, что переменная не контролируется извне.  А это должно быть подавляющее большинство случаев.  В противном случае у вас получается сугубо системное программирование, которое действительно лучше делать на C, а ещё лучше - на ассемблере.

Где-то умножил на 2 вместо 3, вызвал fn() вместо fn_(), ... . Если руки кривые, то беда.

Если умножил на 2 вместо 3, то ты получишь стабильную ошибку в программе, которую легко диагностировать и отыскать.  А при неинициализированной переменной ты получишь чёрти что, которое то работает, то нет, от случая к случаю, с непредсказуемыми последствиями.   Вообще довольно странно, что я объясняю такие азы вам, позиционирующему себя опытным программистом.

 
Alexey Navoykov:

Обмен данных с внешним миром - это уже частные случаи.  И для них нужны особые решения.  А мы говорим о программировании как таковом, и о тех случаях, где компилятор гарантированно знает, что переменная не контролируется извне.  А это должно быть подавляющее большинство случаев.  В противном случае у вас получается сугубо системное программирование, которое действительно лучше делать на C, а ещё лучше - на ассемблере.

Обмен с внешним миром - неотъемлемая часть любой программы. Повторю - иначе её можно вычислить в компайл тайме. Например, вырежет ли здесь компилятор инициализацию?

int i = 54;
if (read_socket() == SIGNAL) {
   fn(i);
}
i = 100;
...

// естественно, что никто не пишет такой бред:
int q = 3;
q = 7;
q = 9;
fq(q);

Очевидно, что он понятия не имеет чего там вернёт read_socket(). Вся программа "пронизана" взаимодействием с внешним миром. + добавьте сюда вызов во внешние модули, ... .

Если умножил на 2 вместо 3, то ты получишь стабильную ошибку в программе, которую легко диагностировать и отыскать.  А при неинициализированной переменной ты получишь чёрти что, которое то работает, то нет, от случая к случаю, с непредсказуемыми последствиями.   Вообще довольно странно, что я объясняю такие азы вам, позиционирующему себя опытным программистом.

Вот смотрите, если хотите получать стабильную ошибку, то инициализировать стек очень просто:

int main() {
    if (true)
        int init_stack[10000] {0};
}

Инициализация памяти из хипа - тоже плёвое дело. Если нарвёмся на какую-нибудь representation trap, то вообще получим core dump.

Ещё раз повторю, если бы оптимизаторы были бы очень умны, то default init приравняли бы к value init с вставкой компилятором инициализурующих инструкций по необходимости ещё в каком-нибудь C11, но увы. Никто не заставляет, если не хотите то, делайте везде T val{}; Усталь объяснять элементарщину.

 
Vict:

Ещё раз повторю, если бы оптимизаторы были бы очень умны, то default init приравняли бы к value init с вставкой компилятором инициализурующих инструкций по необходимости ещё в каком-нибудь C11, но увы. Никто не заставляет, если не хотите то, делайте везде T val{}; Усталь объяснять элементарщину.

Потому что стандарт C++, как я понимаю, описывает правила очень формально, без привязки к контексту.  Т.е. инициализацию либо делать всегда, либо не делать никогда.  Для сравнения, в C# можно объявить переменную без инициализации, но далее по коду она должна быть обязательно проинициализирована. Т.е. компилятор анализирует последующий код, а не только текущую команду, это заложено в правилах языка.  В C++ же никакого анализа не предусмотрено стандартом. Нет гибкости.  Поэтому если пропишут принудительную инициализацию, вы начнёте возмущаться, мол как же так, я сам хочу всё контролировать и инициализировать! )

 
Alexey Navoykov:

Потому что стандарт C++, как я понимаю, описывает правила очень формально, без привязки к контексту.  Т.е. инициализацию либо делать всегда, либо не делать никогда.  Для сравнения, в C# можно объявить переменную без инициализации, но далее по коду она должна быть обязательно проинициализирована. Т.е. компилятор анализирует последующий код, а не только текущую команду, это заложено в правилах языка.  В C++ же никакого анализа не предусмотрено стандартом. Нет гибкости.  Поэтому если пропишут принудительную инициализацию, вы начнёте возмущаться, мол как же так, я сам хочу всё контролировать и инициализировать! )

Просто туда попадают обкатанные решения, а если это будет работать через пень колоду, давая часто лишний оверхед, то никто это не включит. Например, прописали же в стандарте ОБЯЗАННОСТЬ для компилятора делать copy elision в с++17.

 

Тема называется "Ошибки, баги, вопросы".

Пожалуйста, создайте себе тему, в которой будете обсуждать MQL vs C#,C++, и прочее связанное с синтаксисом, компиляторами и разминками для ума.

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

Меня спрашивают где вопрос задать - отправляю сюда, а мне в ответ: там дядьки спорят на сто страниц - не буду мешать, остальное бессмысленно ...

 
const int DEFAULT_INT_VALUE   = 147;
input int thisIsAnInput       = DEFAULT_INT_VALUE;
'NoConstForInput.mq5'    NoConstForInput.mq5    1    1
'DEFAULT_INT_VALUE' - constant expected    NoConstForInput.mq5    13    33
1 errors, 0 warnings        2    1

Build 2361 and 2390

 
Alain Verleyen:
'NoConstForInput.mq5'    NoConstForInput.mq5    1    1
'DEFAULT_INT_VALUE' - constant expected    NoConstForInput.mq5    13    33
1 errors, 0 warnings        2    1

Build 2361 and 2390

#define DEFAULT_INT_VALUE 147
 
Vict:

Вот смотрите, если хотите получать стабильную ошибку, то инициализировать стек очень просто:

Инициализация памяти из хипа - тоже плёвое дело. Если нарвёмся на какую-нибудь representation trap, то вообще получим core dump.

Последний коммент, модераторы не злитесь )).

Тут нужно уточнить - а почему в стеке разные значения от вызова к вызову?. Всё дело в защите https://ru.wikipedia.org/wiki/ASLR, и не нужно даже вообще ничего иницализировать как сказал раннее. В моём случае - запускаю софтину под gdb (отладчиком), который разместит ее по одинаковым адресам при каждом запуске, т.е. стек не будет загажен "случайными" адресами возврата.

Причина обращения: