2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3, 4  След.
 
 Re: struct S* x;
Сообщение30.10.2021, 08:41 
Аватара пользователя


28/10/21
100
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 
Заслуженный участник


18/09/21
1764
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 
Аватара пользователя


28/10/21
100
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 
Заслуженный участник


18/09/21
1764
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 
Аватара пользователя


28/10/21
100
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 
Заслуженный участник


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

 Профиль  
                  
 
 Re: struct S* x;
Сообщение30.10.2021, 10:01 
Аватара пользователя


28/10/21
100
zykov в сообщении #1536994 писал(а):
Пример полной чуши - это утверждать что якобы код
Используется синтаксис C
while(1);
имеет Undefined behavior в C или в C++.


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

 Профиль  
                  
 
 Re: struct S* x;
Сообщение30.10.2021, 10:57 


06/04/18

323
TheRuinedMap в сообщении #1536992 писал(а):
Если у кого-то еще есть вопросы по теме - задавайте
Есть. Попытка использования неинициализированной переменной, как в моем последнем примере, приводит к UB. Что именно подразумевается под UB ? Это совершенно непредсказуемое поведение программы, или оно укладывается в какие-то рамки дозволенного ?

 Профиль  
                  
 
 Re: struct S* x;
Сообщение30.10.2021, 11:05 
Аватара пользователя


11/06/12
10390
стихия.вздох.мюсли
Qlin в сообщении #1536998 писал(а):
Это совершенно непредсказуемое поведение программы
В теории программа может вам хоть жёсткий диск отформатировать. На практике в рамки укладывается.

 Профиль  
                  
 
 Re: struct S* x;
Сообщение30.10.2021, 16:45 
Аватара пользователя


28/10/21
100
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 
Заслуженный участник


18/09/21
1764
TheRuinedMap в сообщении #1537055 писал(а):
компилятор имеет право полагать, что x + 1 заведомо не вызывает арифметического переполнения, а значит условие if является заведомо истинным.
Бред сивой кобылы.

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

 Профиль  
                  
 
 Re: struct S* x;
Сообщение30.10.2021, 18:28 
Аватара пользователя


28/10/21
100
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 
Заслуженный участник


09/05/12
25179
 !  zykov, прекратите личные выпады. Должен заметить, что ваш оппонент достаточно тщательно обосновывает свою точку зрения ссылками на стандарт, поэтому было бы неплохо привести и вашу аргументацию к соответствующему уровню.

 Профиль  
                  
 
 Re: struct S* x;
Сообщение30.10.2021, 23:28 
Заслуженный участник


20/08/14
11867
Россия, Москва
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 


27/08/16
10449
TheRuinedMap в сообщении #1536905 писал(а):
1. "Должна"? Программа имеет неопределенное поведение. Она никому ничего не "должна".
2. Потому что программа, вывод которой в текстовый поток не завершается переводом строки, вообще не обязана ничего никуда выводить.
3. Потому что памяти не существует, пока вы ее сами не распределите (что особенно хорошо видно на платформах с виртуальной памятью). А раз не существует памяти, то не существует и никакого "мусорного значения".
Exterminate!

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

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 53 ]  На страницу Пред.  1, 2, 3, 4  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group