2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1, 2, 3, 4  След.
 
 Re: struct S* x;
Сообщение30.10.2021, 08:41 
Аватара пользователя
zykov в сообщении #1536984 писал(а):
TheRuinedMap в сообщении #1536981 писал(а):
это все - наведенные эффекты
Нет, это фундаментальные эффекты.


Еще раз повторяю: речь идет о буферизации вывода в консоль. В ваших примерах программа не делает вывода в консоль. Поэтому зачем вы нам их постоянно навязываете и какое они имеют отношение к теме - мне в упор не ясно.

Вы уже все уши нам прожужжали про производительность. Это замечательно. Но при чем это здесь???

zykov в сообщении #1536984 писал(а):
TheRuinedMap в сообщении #1536981 писал(а):
То есть никакого while(true); ни в С, ни в С++ не допускается.
Ссылку можно?


Соответствующее место в стандарте С: http://port70.net/~nsz/c/c11/n1570.html#6.8.5p6
Соответствующее место в стандарте С++: https://eel.is/c++draft/intro.progress#1

Более развернутое объяснение на эту тему можно почитать здесь: https://blog.regehr.org/archives/140
Можно посмотреть, как эта тема разрабатывалась комитетом: http://www.open-std.org/jtc1/sc22/wg21/ ... /n2429.htm
Хотя разных ресурсов на эту тему много.

zykov в сообщении #1536984 писал(а):
Я уже не говорю про то, что оно работает на практике.


Это абсолютно ничего не значит. Неопределенное поведение запросто может выглядеть "работающим на практике". К тому же я уже продемонстрировал вам выше, как оно "работает на практике" в clang )))

while (1); часто встречается в программировании микроконтроллеров, по каковой причине GCC возможно еще долго не осмелится поступать с таким кодом агрессивно.

---

Кстати, clang выкидывает такие циклы только в С++ коде. То есть очевидно работает вот это отличие, говорящее о константности управляющего выражения.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 08:50 
TheRuinedMap в сообщении #1536988 писал(а):
Соответствующее место в стандарте С: http://port70.net/~nsz/c/c11/n1570.html#6.8.5p6
Соответствующее место в стандарте С++: https://eel.is/c++draft/intro.progress#1
Посмотрел. Там ничего нет про "неопределенное поведение". Да и поведение тут вполне определенное - бесконечный цикл.
TheRuinedMap в сообщении #1536988 писал(а):
как оно "работает на практике" в clang )))
Вот как раз это ничего не значит. Конкретные компиляторы (в том числе и gcc, что уж говорить про clang) имеют какие-то свои особенности не соответствующие стандарту. Тем более, если применяется агресивная оптимизация, то о стандартах и речи не идёт.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 08:54 
Аватара пользователя
Dmitriy40 в сообщении #1536987 писал(а):
TheRuinedMap в сообщении #1536985 писал(а):
Нет, не изолирует. Попробуйте сами: обычный вывод в консоль дает единицу из isatty(1), перенаправленный вывод дает ноль.
Очень странно на мой взгляд.

Но в любом случае, разве стандарт требует чтобы один из символов потока приводил к выгрузке буферов? Вопрос ведь про стандарт, а не про конкретные реализации.


Я же уже давал ссылку выше на описание стандартной функции setvbuf из стандартной библиотеки языка С

https://en.cppreference.com/w/c/io/setvbuf

которая стандартно поддерживает режим буферизации _IOLBF - построчная буферизация. И да, в режиме построчной буферизации "один из символов потока" - символ перевода строки - обладает особым статусом. Ничего нового или удивительного в этом нет.

Как эта сишная буферизация взаимодействует с надстроенной сверху С++-ной буферизацией и с подсунутой снизу системной буферизацией - вопрос отдельный. Но, согласно экспериментам, все выглядит так, как будто в типичных реализациях на Linux все эти уровни работают согласованно. Я не знаю деталей этого механизма.

-- 29.10.2021, 22:03 --

zykov в сообщении #1536989 писал(а):
TheRuinedMap в сообщении #1536988 писал(а):
Соответствующее место в стандарте С: http://port70.net/~nsz/c/c11/n1570.html#6.8.5p6
Соответствующее место в стандарте С++: https://eel.is/c++draft/intro.progress#1
Посмотрел. Там ничего нет про "неопределенное поведение".


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

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

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

zykov в сообщении #1536989 писал(а):
Да и поведение тут вполне определенное - бесконечный цикл.


Это вы сами его "определили" по своему разумению.

Еще раз: реализациям разрешается убирать из программы пустые циклы.

zykov в сообщении #1536989 писал(а):
TheRuinedMap в сообщении #1536988 писал(а):
как оно "работает на практике" в clang )))
Вот как раз это ничего не значит. Конкретные компиляторы (в том числе и gcc, что уж говорить про clang) имеют какие-то свои особенности не соответствующие стандарту.


Конечно есть. Эти особенности, если они нарушают стандарт языка, называются багами, они регистрируются, документируются и постепенно исправляются.

Данное же поведение компилятора clang является совершенно легальным стандартным поведением. Вы можете, конечно, попытаться зафайлить баг-репорт на эту тему, но в лучшем получите ссылку на все те же объяснения, которые я вам здесь привел. Все это на самом деле не какой-то страшный секрет, а совершенно базовые знания о семантике языков С и С++ с того момента, как они на уровне ядра языка начали принимать во внимание возможность многопоточного выполнения кода. Это нужно знать.

zykov в сообщении #1536989 писал(а):
Тем более, если применяется агресивная оптимизация, то о стандартах и речи не идёт.


А вот это уже полнейшая отвязнейшая чушь.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 09:20 
TheRuinedMap в сообщении #1536990 писал(а):
Там ясно написано, что реализации имеют право полагать, что некоторые виды бесконечных циклов всегда заканчиваются
Именно это и написано. Ничего общего с "неопределенным поведением" это не имеет.
TheRuinedMap в сообщении #1536990 писал(а):
Если ваша программа нарушает правомерные предположения реализации, поведение вашей программы не определено.
Это уже Ваши личные фантазии.
TheRuinedMap в сообщении #1536990 писал(а):
Это вы сами его "определили" по своему разумению.
Нет, это по определению ключевого слова 'while'.
TheRuinedMap в сообщении #1536990 писал(а):
Эти особенности называются багами
А сами такие баги называют фичами.
TheRuinedMap в сообщении #1536990 писал(а):
zykov в сообщении #1536989
писал(а):
Тем более, если применяется агресивная оптимизация, то о стандартах и речи не идёт.

А вот это уже полнейшая отвязнейшая чушь.
Нет, это у Вас проблемы с пониманием предмета.
Вот цитата из gcc man
Код:
       -Ofast
           Disregard strict standards compliance.  -Ofast enables all
           -O3 optimizations.  It also enables optimizations that are
           not valid for all standard-compliant programs.  It turns on
           -ffast-math and the Fortran-specific -fstack-arrays, unless
           -fmax-stack-var-size is specified, and -fno-protect-parens.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 09:28 
Аватара пользователя
zykov в сообщении #1536991 писал(а):
Нет, это у Вас проблемы с пониманием предмета.
Вот цитата из gcc man
Код:
       -Ofast
           Disregard strict standards compliance.  -Ofast enables all
           -O3 optimizations.  It also enables optimizations that are
           not valid for all standard-compliant programs.  It turns on
           -ffast-math and the Fortran-specific -fstack-arrays, unless
           -fmax-stack-var-size is specified, and -fno-protect-parens.


Это говорит лишь о том, что именно в режиме -Ofast компилятор GCC допускает какие-то нарушения стандартной семантики. Но мы до сих пор не вели речи о режиме -Ofast, поэтому я лишь в очередной раз могу удивленно пожать плечами: к чему вы его сюда приплели? Если компилятор в некотором режиме нарушает требования стандарта языка, то этот компилятор в этом режиме не является компилятором этого языка. То есть о нем вообще нет смысла говорить.

Мы же пока что вели речь о поведении, которое никак не нарушает требований стандартов языков С и С++.

zykov в сообщении #1536991 писал(а):
Это уже Ваши личные фантазии.


Во-первых, еще раз повторю (что-то, я смотрю, с первого раза ничего не усваивается): в приведенных дополнительных документах все это очень хорошо разжевано и объяснено. Желающим познакомиться поближе с этой темой еще раз посоветую
N2429: Concurrency memory model (final revision)
N1528: Why undefined behavior for infinite loops?


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

Как я понимаю, Вы пустились в эту степь, чтобы "заболтать" фиаско с темой буферизации вывода. Мне хорошо знакома эта модель форумного поведения. Я думаю, что мне не стоит больше тратить на Вас время.

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

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 09:52 
TheRuinedMap в сообщении #1536990 писал(а):
А вот это уже полнейшая отвязнейшая чушь.
Пример полной чуши - это утверждать что якобы код
Используется синтаксис C
while(1);
имеет Undefined behavior в C или в C++.
TheRuinedMap в сообщении #1536992 писал(а):
я был один из тех людей, чьи "личные фантазии" в течение тринадцати лет, после соответствующей обработки и обсуждения, и становились тем самым стандартом языка С
Да, иногда туда попадают случайные люди. Их мнение выслушивают, но на результат оно не влияет.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 10:01 
Аватара пользователя
zykov в сообщении #1536994 писал(а):
Пример полной чуши - это утверждать что якобы код
Используется синтаксис C
while(1);
имеет Undefined behavior в C или в C++.


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

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 10:57 
TheRuinedMap в сообщении #1536992 писал(а):
Если у кого-то еще есть вопросы по теме - задавайте
Есть. Попытка использования неинициализированной переменной, как в моем последнем примере, приводит к UB. Что именно подразумевается под UB ? Это совершенно непредсказуемое поведение программы, или оно укладывается в какие-то рамки дозволенного ?

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 11:05 
Аватара пользователя
Qlin в сообщении #1536998 писал(а):
Это совершенно непредсказуемое поведение программы
В теории программа может вам хоть жёсткий диск отформатировать. На практике в рамки укладывается.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 16:45 
Аватара пользователя
Qlin в сообщении #1536998 писал(а):
Это совершенно непредсказуемое поведение программы, или оно укладывается в какие-то рамки дозволенного ?


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

1. Неопределенное поведение может проявляться уже на стадии компиляции. А именно: допустимым проявлением неопределенного поведения является отказ компилятора компилировать "неопределенную" программу.

2. Конкретные реализации имеют полное право "доопределять" неопределенное поведение: делать его определенным или ограничивать диапазон его допустимых проявлений "рамками дозволенного" (т.е. фактически переводить его в разряд неспецифицированного поведения).

---

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

Например, при трансляции

Используется синтаксис C
int x;
...
if (x < x + 1)
 


компилятор имеет право полагать, что x + 1 заведомо не вызывает арифметического переполнения, а значит условие if является заведомо истинным.

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

Ссылаясь на вышеприведенный пример с if, зачастую можно услышать чайницкий лепет в стиле "у мне на платформе знаковое переполнение не вызывает неопределенного поведения, у меня будет заворот значения в отрицательные, я знаю, я видел в ассемблере" и т.п. чушь. Компилятору языка глубоко плевать, на ваши знания и на что вы там "видели в ассемблере". Компилятор языка вправе полагать, что условие x < x + 1 заведомо истинно и будет это полагать, если этот компилятор захочет, чтобы его воспринимали всерьез.

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

Еще один замечательный и очень показательный пример - пример для clang, в котором делается попытка вызова функции через нулевой указатель

код: [ скачать ] [ спрятать ]
Используется синтаксис C
#include <stdlib.h>

static int (*Do)(void);

static int EraseAll(void) {
  return system("echo \"I'm formatting your hard drive!\"");
}

void NeverCalled(void) {
  Do = EraseAll;  
}

int main() {
  return Do();
}
 


http://coliru.stacked-crooked.com/a/24e543923f868e20

---

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

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 17:43 
TheRuinedMap в сообщении #1537055 писал(а):
компилятор имеет право полагать, что x + 1 заведомо не вызывает арифметического переполнения, а значит условие if является заведомо истинным.
Бред сивой кобылы.

Qlin
Не обращайте внимания на чушь, которую TheRuinedMap пишет. Он ни бельмеса не смыслит в C/C++. Забил себе голову ерундой с мусорных форумов/блогов.
Qlin в сообщении #1536998 писал(а):
Попытка использования неинициализированной переменной, как в моем последнем примере, приводит к UB. Что именно подразумевается под UB ?
Подразумевается, что результат будет зависеть от значения в памяти, которое непредсказуемо. Скорее всего segmentation fault. Но может попасть в ту область памяти, где не возникает этого. Тогда как-то сработает, но неизвестно заранее как (зависит от этого значения в памяти).

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 18:28 
Аватара пользователя
mihaild в сообщении #1536925 писал(а):
TheRuinedMap в сообщении #1536916 писал(а):
рассмотреть код с точки зрения голого стандарта языка
Естественно, что там напридумывали в реализациях неинтересно (и подозреваю что во всех встречающихся на практике реализациях программа при корректном завершении строку без перевода в конце выведет).


Если вы почитаете дальше http://port70.net/~nsz/c/c11/n1570.html#7.21.2p2, то там также видна вероятная причина, по которой стандарт не хочет определять поведение строки текстового потока, не завершенной символом перевода строки. Стандарт допускает реализации, которые занимаются "оптимизацией" текстовых потоков, а именно: текстовому потоку при записи разрешается "терять" замыкающие пробелы строки, т.е. пробелы, располагающиеся непосредственно перед переводом строки. То есть если вы записали в текстовый файл строку "Hello⎵World⎵⎵⎵\n" (где - пробел) , на физическом носителе и при последующем чтении записанных данных вы можете увидеть просто "Hello⎵World\n" - это допускается стандартом.

Ясно, что в таких реализациях будет просто "непонятно что делать" со строкой, пока она еще не завершена символом перевода строки.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 18:36 
 !  zykov, прекратите личные выпады. Должен заметить, что ваш оппонент достаточно тщательно обосновывает свою точку зрения ссылками на стандарт, поэтому было бы неплохо привести и вашу аргументацию к соответствующему уровню.

 
 
 
 Re: struct S* x;
Сообщение30.10.2021, 23:28 
zykov в сообщении #1537060 писал(а):
Подразумевается, что результат будет зависеть от значения в памяти, которое непредсказуемо.
Нет, не подразумевается, не путайте человека. UB например вообще может быть выкинуто компилятором, без всякого обращения к памяти и значения там. А после его выкидывания часто окажется что и последующий код становится UB (например из-за неинициализированности переменных) или не нужным и тоже выкидывается, вплоть до 99% программы. Для бесконечного цикла это конечно не страшно, но в других случаях это может быть принципиальным, может выкинуться практически весь код.
Ну и для примера последствий можно было хоть вики глянуть (запуск посторонней игры "доставляет по полной" :facepalm: ).

Qlin
Так что UB на то и U что не гарантирует ничего, никаких рамок. В практике рамки конечно есть, но не всегда и они ничем и никем не гарантируются.

TheRuinedMap
Про детский лепет соглашаясь с Вами по существу, всё же добавлю, что иногда можно и правда посмотреть в ассемблерный код и убедиться что ничего страшного компилятор не сделал. Разумеется это не гарантия что он не сделает в следующий раз, даже при перекомпиляции того же исходного кода. И разумеется так писать не стоит. Но если готовы пристально каждый раз следить за результатом, то в таких условиях UB не страшно (UPD. Плохо написал, не "UB не страшно", а конкретно такой исполняемый файл на конкретной аппаратуре уже не вызовет UB и форматирования диска). ИМХО конечно.
За пояснения о буферизации спасибо.
TheRuinedMap в сообщении #1537065 писал(а):
То есть если вы записали в текстовый файл строку "Hello⎵World⎵⎵⎵\n" (где - пробел) , на физическом носителе и при последующем чтении записанных данных вы можете увидеть просто "Hello⎵World\n" - это допускается стандартом.
Вот за такие неочевидные вещи и не люблю стандарт C/C++. Кстати не знал про это.

 
 
 
 Re: struct S* x;
Сообщение08.11.2021, 11:13 
TheRuinedMap в сообщении #1536905 писал(а):
1. "Должна"? Программа имеет неопределенное поведение. Она никому ничего не "должна".
2. Потому что программа, вывод которой в текстовый поток не завершается переводом строки, вообще не обязана ничего никуда выводить.
3. Потому что памяти не существует, пока вы ее сами не распределите (что особенно хорошо видно на платформах с виртуальной памятью). А раз не существует памяти, то не существует и никакого "мусорного значения".
Exterminate!

1. Не знаю, в чём именно человек пишет, но может быть стоит посоветовать ему запустить его разумеется кривую программу под отладчиком без оптимизации и пройти её пошагово? Или отладчики уже запрещены?
2. Да ладно! Процесс сам закрывает все потоки у сбррасывает буфера при нормальном завершении. При ненормальном тоже что-то должно быть написано системой в консоль, про то, что процесс умер.
3. Да ладно! Память под процесс выделяется системой при его создании.

 
 
 [ Сообщений: 53 ]  На страницу Пред.  1, 2, 3, 4  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group