Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
Завезли ссылочные поля класса, это в каком стандарте?
Даже тестил когда то такое, наверное на C++03 и получал ошибку компилятора.
Я и не знал, что добавили такую прекрасную возможность выстрелить себе в ногу.
кстати в крестах есть интересная штука для временных объектов, на которые получены константные ссылки - даже если они выйдут из скопа, то доживут, пока живёт константная ссылка на них
Но в случаях типа UnitedFigure(Figure(...), Figure(...)) она не спасёт. Все фигуры из аргументов прекрасно сдохнут даже если внешнюю попытаться удержать ссылкой.
там j123123 верно заметил, что бугор происходит не в момент, когда ты сделал *f2 при f2=0, а в момент разыменовывания ссылки.
В С++ же нет нулл сейфти, это же не котлин. Ты обязан проверить, что указатель не указывает на говно, прежде чем покласть его результат в ссылку https://govnokod.ru/26958#comment575830
В крестах не бывает «разыменования ссылки». UB происходит строго в тот момент, когда ты получаешь ссылку на nullptr. После этого поведение программы становится не определено, и компилятор волен сделать тебе rm -rf /*.
> и при следующем обращении случается бугор
В этом-то и дело. Багор случается сразу же, как только ты разыменовываешь nullptr. Просто его последствия начинают проявляться позже.
Перефразируя j123123 (https://govnokod.ru/26809#comment575323):
>>> Если ты в крестах используешь какую-то сраную ебучую хуйню, типа разыменования указателя, то ты сам дурак должен соблюдать предельную осторожность с этой хуйней, и вся ответственность за segmentation fault и прочие подобные спецэффекты лежат на тебе. И нехуй в этом винить ссылки
Ну это оно на саму проверку жалуется. В более реальном примере может быть какая-то хуйня, типа
int *crap = (int *)malloc(100500);
на котором этот самый malloc обсирается и возвращает NULL, и потом в некую хуйню передается по ссылке crap[0]
и разыменование нулевой хуйни произойдет по факту не в том месте, где вызвана хуйня shit(crap[0]) а внутри самой функции shit(), которая с этой ссылкой будет что-то делать
Ну оно же говорит, что оно может assume, а значит может все сломать, если там NULL, тоесть выкинуть например воще проверку и будет UB
>и потом в некую хуйню передается по ссылке crap[0]
лол, то есть можно передать уже говно, и узнать о том, что ты передал говно через три часа в другом месте?
По сути у тебя будет ссылка на нул, да)
Проверил. Такая хуйня скомпилировалсь, и упала. Какой багор))))
int* foo()
{
return NULL;
}
int main()
{
int& bar = *foo();
std::cout << bar;
return 0;
}
Указатель тоже можно проверять ПЕРЕД передачей в хуйню. Но указатель можно проверять и внутри хуйни, поэтому я за указатели. Ссылки просто нахуй не нужны
а можно ссылку обратно в указатель катсануть, и проверить, на что она показывает?
Я не крестовичок, но так понимаю, что ссылки умнеьшают количество семантического мусора, и не заставляют клиента "знать" про ссылку.
class VeryHugeObject
{
public:
void doAll()
{
return;
}
};
void foo(VeryHugeObject &a)
{
a.doAll();
}
int main()
{
VeryHugeObject a;
foo(a); //может копируется он, а может нет, пишеца одинаково. С указателем так низчя
return 0;
}
Но как любая абстракция ссылка не бесплатна для мозга. Нужно понимать теперь что там происходит н а самом делде
Ну так действительно нельзя
Там будет такая же хуйня с варнингом на строчке if (&bar == NULL)
prog.cc:11:18: warning: the compiler can assume that the address of 'bar' will never be NULL [-Waddress]
у вижал си не будет (ну у меня нет по край мере), но линтер шланга меня отругал
reference cannot be bound to dereferenced null pointer in well-defined c++ code
То есть катсинг-то сам по себе валиден (взять адрес того, на кого указывает ссылка), а вот проверка оного на нул -- варнинг
> Напоминаю, что вот здесь:
>> *(int *)0
>У тебя произошло UB
Если внимательно посмотреть, я использую особую опцию "-fno-delete-null-pointer-checks" от которой компилятор ложит хер на ту часть стандарта, которая запрещает разыменовывать NULL.
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
> -fdelete-null-pointer-checks
>
> Assume that programs cannot safely dereference null pointers, and that no code or data element resides at address zero. This option enables simple constant folding optimizations at all optimization levels. In addition, other optimization passes in GCC use this flag to control global dataflow analyses that eliminate useless checks for null pointers; these assume that a memory access to address zero always results in a trap, so that if a pointer is checked after it has already been dereferenced, it cannot be null.
>
> Note however that in some environments this assumption is not true. Use -fno-delete-null-pointer-checks to disable this optimization for programs that depend on that behavior.
>
> This option is enabled by default on most targets. On Nios II ELF, it defaults to off. On AVR, CR16, and MSP430, this option is completely disabled.
>
> Passes that use the dataflow information are enabled independently at different optimization levels.
Но видимо этот флаг не запрещает компилятору предполагать, что ссылка не может быть с NULL.
Пардон, пардон, а причём здесь вообще какие-то опции и детали реализации компилятора? Ты привёл пример невалидной программы на «C++» и почему-то обвиняешь в получившихся баграх ссылки.
Невалидная она только с точки зрения питушарского крестостандарта, а если компилятор разрешает ложить болт на него, то это уже не проблема. У меня вполне может быть какой-нибудь говноконтроллер, где прочитать или записать хуйню по нулевому указателю вполне может иметь смысл, например чтоб таблицу векторов прерываний поменять.
Надо просто ввести новую опцию -fallow-null-in-references
> а если компилятор разрешает ложить болт на него, то
…то ты пишешь не на «C++», а на другом языке. С тем же успехом я могу ругать сишные структуры за какие-то багры в «Cython».
> где прочитать или записать хуйню по нулевому указателю вполне может иметь смысл
По Стандарту, кстати, никакого «нулевого» указателя не существует. Конкретный адрес nullptr и NULL выбирает платформа. Синтаксис «T * ptr = 0;» является синтаксическим сахаром:
A null pointer constant is an integer literal (5.13.2) with value zero or a
prvalue of type std::nullptr_t.
A null pointer constant can be converted to a pointer type; the result is the null pointer
value of that type (6.8.2) and is distinguishable from every other value of object pointer
or function pointer type.
§ 7.3.11/1 (N4842)
Именно поэтому читать-записывать по нулевому адресу тебе никто* не мешает:
Только вот тогда получается так, что на настоящем «C++» не пишет вообще никто, т.к. ни один компилятор крестоговна на данный момент не реализует стандарт на 100%
> The SQL standard is huge. More than 4300 pages in its SQL:2016 incarnation. No single implementation can ever implement all features.0 Even in the early releases, such as SQL-92, the SQL standard defined different conformance levels so that vendors can claim conformance to a subset of the standard.
Почему кстати в стандарт крестоговна не ввели эти «conformance levels»? По-моему вполне логичный шаг.
Повторюсь: причём тут компиляторы? Это ты пишешь исходный код программы, а не компилятор. Если твой исходный код соответствует Стандарту, то ты пишешь на «C++», если не соответствует — то ты пишешь на каком-то другом языке с другими правилами и другими баграми. Вот и всё.
Потому что указанный код содержит undefined behavior. Это означает, что компилятор волен делать что угодно, включая компиляцию «Тетриса» из твоих исходников.
Ну да, так уж кресты устроены.
Как, впрочем, и няшная сишка: там тоже есть UB и оно точно так же может через карман укусить за яйца. С другой стороны, в §J.2 (N2346) приведён полный список сишных UB, так что их можно более-менее заучить и не допускать. С третьем стороны, этот список занимает десять страниц A4.
Я её выдумал. Но пишется за пару минут. В конструкторе проверишь, что не нулл и бросишь исключение. А дальше можно таскать без проверок и потерь пирфоманса.
Ну по-хорошему да. Не верить же автору сторонней либы на слово? Тем более сишные либы так сигналят об ошибке и тебе один хер проверять. А в крестах тебе голый указатель не так уж часто возвращают.
> int& petuh = *get_petuhz();
Если ты уверен, что get_petuhz() тебе никогда не вернёт nullptr — можешь делать так безо всяких проверок. В этом и есть смысл крестов (да и няшной тоже): ты можешь делать «опасные» операции безо всяких проверок, если считаешь, что они всегда будут корректны.
Однако если твоя уверенность тебя подведёт и get_petuhz() таки вернёт nullptr — ты получишь UB, и дальше твоя программа может делать абсолютно что угодно.
Смех-смехом, а твоя мамка кверху мехом.
а я придерживаюсь тех же взглядов. Компилятор/интерпретатор должен только проверять корректность синтаксиса, и никак не обучать тебя каким-то типизациям и, тем более, заставлять тебя удалять неиспользуемые переменные (как в "Go").
> Если твой исходный код соответствует Стандарту, то ты пишешь на «C++»
Текст стандарта крестоговна написан на английском и не является строго формализованным описанием, так что там еще хуй поймешь, можно над каким-то пунктом рассуждать как жиды над торой, что там говностандартизаторы в этом пункте имели в виду. Надо написать четкую формальную спецификацию, чтоб никаких разночтений не было, потом уже говорить, что можно писать на каком-то мифическом «C++»
Текст Стандарта написан на вполне себе формальном и строгом английском языке. Баги там, безусловно, бывают, но не в этом случае. Много нужно рассуждать над фразой «In particular, a null reference cannot exist in a well-defined program»?
> Надо написать четкую формальную спецификацию
Написали. Называется «Стандарт».
> разночтений
Приведи реальный пример разночтений в Стандарте.
Это не четкая формальная спецификация. Это текстовая человекочитаемая хуйня на естественном языке, которую можно по-разному понять и проинтерпретировать своим мозгом.
> Приведи реальный пример разночтений в Стандарте.
Могу привести реальный пример, когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать
Ты удивишься, но математические доказательства тоже по большей части пишутся на человекочитаемом естественном языке. Теперь у нас вся математика отправляется в утиль?
> Давайте с memcpy, с ним проще. Я смотрю по C++17 draft, но для простоты и тех, кто не хочет грузить 1500-страничные пдфки, даю ссылки на онлайн-версию, где стандарт уже немного другой.
> Так вот, 6.8/2 и /3 говорят, что вы можете делать memcpy для объектов trivially copyable типов (в частности, если они не являются подобъектами), даже если они не содержат валидного значения. И как мы видим из 11.2/1, наличие конструктора по умолчанию никак не влияет на свойство trivially copyable.
> Надеюсь, этого достаточно, чтобы разобраться с memcpy.
> А вот с memset всё интереснее. Он в стандарте упоминается всего несколько раз, и все эти разы — без описания семантики. Поэтому вопрос о том, что разрешено делать с memset, является совсем неочевидным. Ответ «memset в коде на плюсах использовать нельзя вообще», похоже, стандарту не противоречит.
И в ответе:
> Ну в самом же деле, нельзя же ожидать, чтобы в стандарте были перечислены вообще все допустимые случаи использования любых комбинаций функций из стандартной библиотеки.
Ну а где здесь разночтения-то? Уважаемый 0xd34df00d просто не разобрался. Крестостандарт нам говорит:
The contents and meaning of the header <cstring> are the same as the C standard library header <string.h>.
§ 21.5.3/1 (N4842)
Идём в «C standard», читаем:
7.24.6 Miscellaneous functions
7.24.6.1 The memset function
Synopsis
1 #include <string.h>
void *memset(void *s, int c, size_t n);
Description
2 The memset function copies the value of c (converted to an unsigned char)
into each of the first n characters of the object pointed to by s.
Returns
3 The memset function returns the value of s.
2 Normative references [intro.refs]
1 The following documents are referred to in the text in such a way that some or all of their content constitutes
requirements of this document. For dated references, only the edition cited applies. For undated references,
the latest edition of the referenced document (including any amendments) applies.
(1.1) — Ecma International, ECMAScript Language Specification, Standard Ecma-262, third edition, 1999.
[...]
(1.5) — ISO/IEC 9899:2018, Programming languages — C
30.13 Modified ECMAScript regular expression grammar [re.grammar]
1 The regular expression grammar recognized by basic_regex objects constructed with the ECMAScript flag
is that specified by ECMA-262, except as specified below.
Да и само содержимое хедера <string.h> нихуя не описывает поведение функций memset, там просто описывается что есть такие-то функции, принимающие такие-то аргументы. Так можно еще долго доебываться
Надо четко написать, что такие-то функции ведут себя точно так же, как ведут себя функции Си такого-то стандарта. А что такое meaning какого-то хеадера сишки? Просто определение функций, а что они делает - хуй знает. Это вам не крестоговно, когда там какие-то шаблоны с кодом запилены.
Ну как это не описывает, когда описывает? Я же цитату из няшного Стандарта привёл.
>>> The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.
Тут разве что приебаться можно к «first n characters of the object pointed to by s», но это нужно хорошенько задрочить крестовый object representation или как его, а там дохуя листов A4 формального английского, который нашему отделу чтения и парсинга обрабатывать лень.
Ну вот как мне конкретно понимать значение «contents and meaning»?
contents - содержимое. Там содержатся какие-то определения функций. Т.е. инклудя <cstring> мы инклудим то же, что и в <string.h>
meaning - значение. Ну т.е. смысл того что заинклужено. А смысл в хедере там такой, что вот такие-то функции есть, которые принимают такие-то аргументы и возвращает такую-то хуйню. Хедер сам по себе не описывает то, что конкретно какая функция делает. Так что надо четко сказать, что функии, определенные в таком-то хедере, делают то же самое, что они делают в сишечке такого-то стандарта.
> А смысл в хедере там такой, что вот такие-то функции есть
На самом деле хорошая приёбка, но, тем не менее, Стандарт может противостоять даже таким дотошным людям!
The library described in Clause 7 of ISO/IEC 9899:2018 is hereinafter called the C standard library. (1)
1) With the qualifications noted in Clause 17 through Clause 32 and in C.6, the C standard
library is a subset of the C++ standard library.
§ 2/2
> Ну может это означает что-то в духе
Всё есть в Стандарте.
16.4.1.5 C library [structure.see.also]
1 Paragraphs labeled “See also” contain cross-references to the
relevant portions of other standards (Clause 2).
> когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать
И тем не менее, после качественной раскопки Стандарта разночтений выявлено всё ещё не было. Отсутствие строгого определения слова «meaning» полностью компенсируется примечанием 1.
Научная фантастика и научная реальность в информатике
Эдсгер В. Дейкстра
...
Чуть раньше я упомянул плохую документацию системы как внутреннее ограничение надежности, с которой система может быть использована механически в более широком контексте. Теперь самое время указать, что привлечение технического писателя редко является выходом из положения; в сущности, это не более как признание того, что разработчики системы в некотором роде функционально безграмотны. Обычно даже целая армия технических писателей не может справиться с задачей, поскольку система становится столь сложной, что не поддается точному описанию.
Выдающийся пример этого явления недавно продемонстрировала Ada. Если Ada собирается выдать стандарт, желательно, чтобы он был недвусмысленно документирован. По меньшей мере две группы попытались сделать это; в результате обе выдали около 600 страниц формального текста. Это гораздо больше, чем необходимо, чтобы удостовериться в невозможности хотя бы твердо установить, что оба документа определяют один и тот же язык. Ошибка очевидной неуправляемости этих двух документов кроется ни в двух группах, составивших их, ни в принятом ими формализме, а лишь в самом языке: сами не обеспечив формального определения, могут ли его разработчики скрыть, что они предлагают неуправляемого монстра. То, что Ada уменьшит проблемы программирования и увеличит надежность наших разработок до приемлемых границ, - это лишь одна из тех сказок, в которые могут поверить только люди с военным образованием. Самое лучшее, что я могу сказать об этом, - это упорные слухи, что даже военного образования недостаточно, чтобы поддерживать веру в этот Философский Камень. Я упомянул про Ada, поскольку это замечательный пример того, на что я указывал в начале доклада: ее принятие - это политический процесс, в котором информатике, предостережения которой рассматривались как досадная помеха, не было дозволено оказывать никакого влияния. Следовательно, даже простое согласие с чьим-то обоснованным сомнением на этот счет, даже без вмешательства в контроль и намерения, становится действием с политическим душком.
При этом в языке Ада строгая тупизация с предикатами (фактически это контрактное программирование), а слабая неявная тупизация JS заставляет срать кирпичами.
Тем не менее, популярность языка совершенно никак не проистекает из его качества. JS в этом смысле даже вызывает больше уважения, чем пыхи и питоны, потому что у JS хотя бы есть спецификация (хотя некоторым на нее срать -- вспоминаем typeof(null)), просто люди выбирают тот язык, который сейчас популярен, и который позволяет решать нужные задачи
Если бы в браузер была встроена ада, то все бы на ней писали, и текли, и не жужжали, и меньше было бы в мире undefined, Nan и [Object object].
Потому что статическая типизация позволяет отловить больше ошибок на уровне комплияции. Это же очевидно. Именно потому MS изобрёл TS.
смотри, вот я модный и использую подгрузку
это означает что бандл у меня поделен на файлы, файлы подгружаются асинхронно, для работы сайта в первую секунду нужен один, а все остальные догружаются в течении минуты, а какие-то через 10 минут
при этом в коде файлы считают друг друга модулями
как это реализовать на компилируемых языках?
Я всё-таки надеюсь, что ты не собираешься вызывать функции из незнакомой DLL.
Список символов получить можно. А вот семантику параметров функций нужно знать. В JS ты же тоже не знаешь, для чего какой аргумент у функции из чужого скрипта.
Малость дизасмишь саму длл.
Малость дизасмишь проги, которые её юзали.
Много примеров использования получаешь.
Это в нашей чеховской-кибальчеховской все-все знают.
если ты знаешь колконвеншен, и ты при этом скилловый питуз, то ты можешь попробовать угадать типы аргументов
А чтобы понять семантику нужно или смотреть как ее вызывают (как сказал броманд) или читать асм. Но это вообще для суперскиловых чуваков, которые живут одновременно с Олькой и Идой
Кстати да, можно еще доебаться до того, что char в крестах и char в сишке может определяться слегка по-разному, семантика указателей может быть разная, и просто так сказать типа "чтобы понять что эта хуйня делает, почитайте текст другого стандарта" - не очень хорошая идея
> Надо четко написать, что такие-то функции ведут себя точно так же, как ведут себя функции Си такого-то стандарта.
Ну так там это и написано. Для каждого хедера из стандартной либы (что крестов, что няшной) есть отдельный раздел, в котором описываются meaning соответствующих функций.
В крестовом Стандарте в описании <cstring> даже ссылка есть на соответствующий пункт няшного («See also: ISO C 7.24»).
> Для каждого хедера из стандартной либы (что крестов, что няшной) есть отдельный раздел, в котором описываются meaning соответствующих функций.
Там же про meaning хедера говорится, а не про meaning функций.
Ну и вот мы тут как раз еще один пример получили, когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать, как ты и просил в https://govnokod.ru/26958#comment575919
> даже ссылка есть на соответствующий пункт няшного («See also: ISO C 7.24»).
Мало ли что это может значить? Ну может это означает что-то в духе "ну вот может ну нахуй это крестоговно, вот посмотрите лучше стандарт сишки, там прикольней написано".
> Именно поэтому читать-записывать по нулевому адресу тебе никто* не мешает:
> int value_at_zero = *(int *)(1 - 1);
Тут кстати можно не согласиться.
Если хуйня «(1 - 1)» после вычислений дает то же, что и дает NULL (допустим если в хедере есть «#define NULL 0», и при этом из курса школьной математики нам известно, что «1-1=0»), то получим UB (даже если там валидный объект). Если «*(int *)(1 - 1)» дает ту же хуйню, что и «*(int *)nullptr» - получем ту же UB хуйню (даже если там валидный объект)
> после вычислений дает то же, что и дает NULL
В этом и весь смысл: (1 - 1) и 0 в контексте нулевого указателя — это разные вещи. Простой нолик-литерал — это синтаксический сахар, к нулевому адресу не имеющий никакого отношения. Поэтому из NULL == 0 вовсе не следует, что (int *)(1 - 1) — это нулевой указатель.
> Если «*(int *)(1 - 1)» дает ту же хуйню, что и «*(int *)nullptr» - получем ту же UB хуйню
А так будет только тогда, когда компилятор считает нулевой адрес за nullptr. Очевидно, если на какой-то платформе нулевой адрес валиден, то компилятор nullptr в него раскрывать не будет. Ну, если его не лалки анскильные писали, конечно.
Тяжёлое наследие сишного режима. В те стародавние времена никто не подумал, что в 0x0 может быть что-то валидное записано, вот и сделали 0 === NULL. В крестах одумались и для нулевого указателя запилили nullptr без привязки к числам, но было уже поздно, и пришлось городить такие вот говнокостыли.
В досовских программах адрес 0x0 вполне мог использоваться для чтения и установки вектора прерывания №0. Но в программах на ЯВУ обычно нулевой указатель не разыменовывали, а пользовались библиотечными функциями (что-то типа _dos_setvect, _dos_getvect).
На UEFI, к слову, там тоже лежит реалмодная IDT. И ты невозбранно можешь писнуть в нулл и сломать прошивочный видеодрайвер, если у тебя видюха со времён windows 7.
Выше цитату привёл, про «A null pointer constant is an integer literal (5.13.2) with value zero». И вот: https://wg21.cmeerw.net/cwg/issue903
>>> There was a strong consensus among the CWG that only the literal 0 should be considered a null pointer constant, not any arbitrary zero-valued constant expression as is currently specified.
Причём до C++11 нулевым указателем считалась любое нулевое константное выражение, что приводило к такому багру:
void f(void *); // #1
void f(...); // #2
template<int N> void g() {
f(0*N); // calls #2; used to call #1 [gost: used to — это до C++11]
}
> В этом и весь смысл: (1 - 1) и 0 в контексте нулевого указателя — это разные вещи
Есть реальные примеры, где это были б разные вещи? https://wandbox.org/permlink/awAHb63ePcdv8Jal - я что-то не нашел.
0 должен создать указатель с "пустым" значением на этой платформе (FF'ки какие-нибудь?). А 1-1 просто с нулевым. Ну если я правильно понял цитаты госта.
По-моему это хуйня какая-то. «0» и «(1 - 1)» это один хер с точки зрения компилятора. Пусть гост приведет убедительные доказательства со ссылками на говностандарт, что «(int *)(1 - 1)» и «(int *)0» по стандарту могут давать разную хуйню
constexpr uintptr_t govno = 0;
void *hui1 = reinterpret_cast<void *>(govno); // hui1 — указатель на адрес 0x0
void *hui2 = 0; // hui2 — указатель на адрес nullptr, зависит от платформы
> Ну и хуйня ваши кресты.
Ну а как ещё соблюсти два условия:
1) Иметь «нулевой» указатель nullptr, который на текущей платформе всегда будет невалиден;
2) Иметь возможность писать в любые адреса, поддерживаемые платформой, включая 0.
?
> 1) Иметь «нулевой» указатель nullptr, который на текущей платформе всегда будет невалиден;
В теории можно изобрести такую платформу, где абсолютно все указатели будут валидны, так что это условие по-сути своей - хуйня полная.
> 2) Иметь возможность писать в любые адреса, поддерживаемые платформой, включая 0.
Это можно было б решить какой-нибудь нестандартной хуйней, например специальным оператором разыменования или встроенной функцией, которая подразумевает что через нее можно можно и нулл разыменовать, и нихуя плохого в этом нет. Типа вместо
int hui = *(* int )0;
делаем
int hui = __buildtin_superduper_dereference((* int )0);
> В теории
А на практике такая платформа нахуй не нужна.
Нулевой указатель нам нужен не для того, чтобы UB генерировать, а чтобы на него, внезапно, проверять. Вот есть у нас malloc(), она нам может вернуть либо указатель на выделенную память, либо nullptr/NULL в случае, если что-то пошло не так. Если у нас все указатели валидны — мы сосём хуй.
> специальным оператором разыменования
Ну и плодим никому не нужные сущности. Вместо этого разумнее было бы лишние сущности удалить, и за нулевой указатель считать только платформозависимый NULL/nullptr. Тогда мы спокойно можем писать по любому валидному числовому адресу, и никаких багров не возникает.
int *null = NULL; // «Нулевой» указатель
int *zero_addr = 0; // Адрес 0
printf("%d", *zero_addr); // Если платформа поддерживает нулевой адрес — всё заебись
if (!null /*null == NULL*/) {
// Выполнится всегда
}
if (!zero_addr /*zero_addr == NULL*/) {
// Выполнится только если на текущей платформе
// нулевой указатель равен нулю
}
A prvalue of arithmetic, unscoped enumeration, pointer, or pointer-to-member type can be converted to a
prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false;
any other value is converted to true.
>Вот есть у нас malloc(), она нам может вернуть либо указатель на выделенную память, либо nullptr/NULL в случае, если что-то пошло не так.
Эта хуйня без NULL-питухов решается - в malloc просто возвращаем структуру, которая состоит из bool и из поинтера. Если в буле false то значит malloc обосрался с выделением памяти, если в буле true то значит все норм, и из другого члена этот поинтер читаем и чето с ним делаем.
> структуру, которая состоит из bool и из поинтера
Только вот есть проблема: обычно размер указателя равен размеру регистра, поэтому твоя структурка в [er]?ax не поместится. Как результат — придётся на каждый вызов любой функции, потенциально возвращающей NULL, лишний раз дрочить память, а это пиздец пирфомансу.
А есть ли реальные примеры частовызываемых и быстроработающих функций, которые могут потенциально возвратить NULL, переделка которых на хуйню со структурой приведет к заметному падению пирфоманса?
На практике нахуй не нужны языки, которые указывают, какие платформы нужны, а какие нет.
Если взять например 8-bit AVR говноконтроллеры и почитать memory map из даташита, то там на нулевых адресах хранятся значения регистров, т.е. регистры можно прочитать из памяти таким вот образом. Если используется malloc() хуйня, то конечно же она в регистрах нихуя выделять не должна, так что для обозначения того, что malloc() обосрался, вполне можно использовать адрес 0x0000, и для этого не надо никакой хуйни с гарантировано невалидными адресами, которые разыменовывать нельзя, достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
> то там на нулевых адресах хранятся значения регистров, т.е. регистры можно прочитать из памяти таким вот образом
И шо, все остальные адреса валидные? Прямо от 0 до 0xFFF…?
> достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
Ок, хочу функцию
int *get_registers_mapping();
И чтобы она на тех контроллерах, на которых маппинг регистров в память поддерживается, возвращала мне этот адрес, а на тех, где не поддерживается — об этом сообщала. Вызывать её будем триллион раз в час.
Ну вот тут https://scienceprog.com/avr-microcontroller-memory-map/ написано что начиная с RAMEND+1 адреса идет External RAM вплоть до 0xFFFF. Если ее реально всю дозаполнить реальной памятью, то тогда похоже что да, все адреса там так или иначе будут за что-то отвечать.
>чтобы она на тех контроллерах, на которых маппинг регистров в память поддерживается, возвращала мне этот адрес, а на тех, где не поддерживается — об этом сообщала.
А нахуя? Почему б тебе не узнать о неподдерживаемости на этапе компиляции (или на этапе чтения даташитов на конкретный говноконтроллер)?
> avr-microcontroller-memory-map
Принимается. Да, у 16-битных (и меньше) контроллеров с лишней памятью проблемы. Их владельцам можно посоветовать либо использовать компилятор, производитель которого явно задекларировал, что в нём обращаться к NULL можно, либо хуярить асмовставки, благо из них обращаться к любым адресам никто не запрещает.
> А нахуя? Почему б тебе не узнать о неподдерживаемости на этапе компиляции (или на этапе чтения даташитов на конкретный говноконтроллер)?
Потому что надо.
Ну а вообще я к тому, что вот это:
>> достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
— плохое, неконсистентное решение. Если я могу прочитать данные по какому-то указателю, то почему он должен считаться невалидным?
Выходит, что сишечка++ требует от платформы в жертву как минимум один адрес (лучше всего нулевой) для невалидного указателя, и без костыля ее на малипусиньких процах не запустить?
> 1) Иметь «нулевой» указатель nullptr, который на текущей платформе всегда будет невалиден;
А зачем для этого считать (void *)0 не тем же самым, что и (void *)(1-1) ? Ну пусть бы был какой-то nullptr который на одной платформе равен какому-нибудь 0xFFFFFFFF, на второй равен 0xDEADC0DE, на какой-то другой - еще какой-то хуйне, зачем его синонимировать с литералом 0? Чтоб с сишкой была совместимость?
#include <cstdint>
int main() {
constexpr uintptr_t zero = 0;
// int *foo1 = (1 - 1); // error: invalid conversion from 'int' to 'int*' [-fpermissive]
// int *foo2 = zero; // error: invalid conversion from 'uintptr_t'
// {aka 'long unsigned int'} to 'int*' [-fpermissive]
int *foo3 = 0;
return 0;
}
«GCC» Стандарт понимает правильно и выдаёт вышеуказанные ошибки. А вот «Visual Studio» последней версии на них кладёт болт и успешно компилирует все три примера. Какой багор )))
Даже если у тебя какая-то платформа, где нулл можно юзать, ну положи туда какую-то структуру, на которую ты никогда не будешь брать указатели, которые могут быть невалидными. Ту же таблицу прерываний. Всяко что-то такое у тебя есть.
И не надо портить платформу и городить костыли на ровном месте.
И явный UB про разадресацию nullptr тоже можно убрать. Он ничем не отличается от любого другого указателя на мусор.
> И не надо портить платформу и городить костыли на ровном месте.
Какие костыли-то? Отдельный NULL/nullptr без привязки к конкретным числам — вполне себе заебись решение.
> И UB про разадресацию nullptr тоже можно убрать.
UB нельзя убирать, UB — это священная корова оптимизации!
int i = 0;
int* q = (int*)i; //вот что тут будет?
if (q == NULL) //а тут что?
Я понимаю, что так кастить нельзя наверное (особенно из инта) но всё таки есть код, который уже так написан, и я до сегодняшнего дня не думал, что он может не работать
> это питон же.
Дык в любом языке с nullable ссылками дошли до того, что неплохо бы иметь специальное значение для пустой ссылки.
> int* q = (int*)i; //вот что тут будет?
С принудительным кастом — указатель на адрес 0.
> if (q == NULL) //а тут что?
Зависит от платформы.
Проблема не в принудительном касте, проблема в неявном. По-хорошему, надо было полностью запретить неявные касты из любых чисел в указатели. Хочешь инициализировать указатель пустым значением — пиши «ptr = NULL», а не выёбывайся с «ptr = 0».
Но, разумеется, теперь Боржоми пить поздно, совместимость с сишкой выкинуть не получится.
Соглашусь. Впрочем, я регулярно наблюдаю такой ворнинг (гцц его пишет) при компиляции какого-то говна в линукс, так что не все питухи одинаково скилловы
> А UB про "специальное значение"
Дык NULL — это по определению невалидный адрес.
> в духе выбрасывания проверки на нулл потому что я уже обратился
Дык уязвимость-то будет не в выбрасывании проверки на нулл, а в самом обращении. После обращения к указателю проверка на нулл полностью бессмыслена.
Скажем так, это просто адрес, который не может быть выделен аллокатором, описанным в стандарте (ну и не может принадлежать локалке и т.п.) Поэтому я его могу юзать как маркер пустоты или как маркер ошибки. И это удобно для всяких структур данных.
Но он, имхо, ничуть не более невалидный, чем указатель на какой-нибудь ROM или MMIO, который я тоже по стандарту получить и юзать не могу, лол.
Зачем его делать пиздец-пиздец невалидным и особенным - я х.з.
> Зачем его делать пиздец-пиздец невалидным и особенным - я х.з.
Дык он и никакой не особенный. Обращение к нему — точно такое же UB, как и обращение к любому другому невалидному адресу.
>> В код по ошибке просочилось чтение.
>> А дальше пошло исполнение кода.
Какое исполнение-то? Чтение тебе кинуло SIGINT и всё, привет.
Но при обращении к любому другому невалидному (согласно стандарту) адресу не взводится факт, что он теперь валидный! И не выбрасываются никакие проверки!!
Почему нулл то в этом плане особенный? Потому что весь код засрали проверками на него, а теперь тормозит?
Ну и чтобы не пиздеть, вот что по этому поводу говорит Стандарт:
A reference shall be initialized to refer to a valid object or function.
[Note: In particular, a null reference cannot exist in a well-defined program,
because the only way to create such a reference would be to bind it to the “object”
obtained by indirection through a null pointer, which causes undefined behavior.
§ 9.3.3.2/5 (N4842)
Так что жаловаться на null в ссылках — это как сделать строку без \0 в конце, а потом ругать «strlen()» за то, что она падает.
А хэшмапы и деревья — это просто сахарок над массивами!
> и устроить true == false
Кстати, в прошлом году на ГК это обсуждали: делали memcpy() в буль-буль переменную и наблюдали за весёлыми эффектами на разных компиляторах. Кажется, там ещё какой-то конпелятор проверял чётность буль-буля и 2 считал за false.
> А что не так?
Присвоишь ты в это поле ссылку на объект в другом скопе, он уничтожится и получишь SEGFAULT, и будешь потом долго искать в чем дело, а найдя будешь переписывать свой монолит.
> по твоему поля всегда должны копироваться чтоли?
умные указатели, RAII, а не это уж точно.
Вероятно тем, что f2 ты можешь проверить на нул, и это будет валидно)
А ссылку не можешь (точнее можешь, но компилятор может такую проверку выкинуть, бо будет считать, что она всегда фолс))
Но я не защищаю эту позицию. Я не крестовик, но мне тоже нравится null safety. Во всяком случае в джавах и котлинах мне нравится знать, что поле никогда не может быть нулом, и не проверять его каждый раз, как дурак
Ну дык ТС про null вообще ничего не говорил, это мы тут начали питушиться.
> Во всяком случае в джавах и котлинах мне нравится знать, что поле никогда не может быть нулом, и не проверять его каждый раз, как дурак
Подтверждаю.
Кстати, если уж развивать мысль — в «Ко-ко» же можно какой-нибудь грязной рефлексией в поле типа T записать null?
ТС вообще не нравится, что ссылка не влияет на время жизни объекта, и ты должен сам вручную вот это всё.
В коко можно записать рефлексией.
А еще можно дернуть метод джавы, про который не известно нулл он или нет.
А еще можно написать "!!"
fun foo(o: SomeJavaObject): String {
return o.getNull() //коко не знает нул там или нет
}
fun foo(o: SomeKokoObject): String {
return o.somethingThatReturnsNull()!! //тоже багор
}
Вполне можно NPE получить при определенных навыках)
>Присвоишь ты в это поле ссылку на объект в другом скопе, он уничтожится и получишь SEGFAULT
С ссылками и поинтерами вообще такая проблема есть в крестах, угу.
>умные указатели
Ну так используй умные указатели в полях, это же можно наверное?
> умные указатели
Умные указатели нужны тогда, когда наш класс владеет объектом (за исключением std::weak_ptr, но это специфическая штука). А когда класс должен ссылаться на какой-то объект, очевидно, приходится использовать либо указатели (и ловить багры от nullptr), либо ссылки (и ловить багры от невозможности изменить объект, на который указывает ссылка).
Если класс не владеет объектом, то ты обязан гарантировать ему, что объект не помрет, покуда инстанс твоего класса живой, а товарищу же это не нравится.
Ну я так понял, что YpaHeLI_в принципе против «ссылочных полей». Вот я и спрашиваю, как он произвольное ссылочное поле будет заменять на умный указатель.
> Для данного класса какой-нибудь unique вполне сойдёт.
А вот не факт. Я, может, не хочу ебать кучу, а хочу
На самом деле, лучше научить конпелятор немного рассуждать о ссылках. Если ссылка никуда не уходит, то можно спокойно оставлять всё на стеке, пидорасить на отдельные поля в регистрах и т.п.
Тогда всегда пишешь как для кучи, а конпелятор сам разберётся.
Жабий жит вроде умеет такое. Кресты пока нет, но собираются добавить в стандарт возможность выпиливать пару new/delete.
Ну крестоконпеляторы тоже умеют такое доказывать и юзать. Но вот саму пару new/delete они пока не могут выпилить т.к. там кода пиздец дохуя и его не заинлайнить. Нужна более жёсткая семантика для new и delete, чтобы для конпелятора они были не просто парой функций которые делают произвольную хуйню.
C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений. Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист. Умение героически преодолевать трудности, которые создает твой собственный инструмент, вместо того, чтобы решать непосредственно прикладную задачу, в современном мире ценится разве что только среди прыщавых сосок. Работодатель же это сомнительное умение не ценит, и совершенно справедливо.
Важное заявление.
Аккаунт MAKAKA был взломан хакером (кажется, инью). Возможно, он использовал Meltdown уязвимость моего процессора, или тот факт, что пароль от аккаунта был 123, но тем не менее этот аккаунт более мне не принадлежит.
пиндосы догоняют раш-ку с украш-кой в вопросах свободы и демократии
Начиная с 20 сентября AppStore, Google Play и другие должны будут удалить китайские приложения из соображений нацбезопасности, следует из заявления Министерства торговли США, опубликованном на сайте.
gost # 0
> прекрасную возможность выстрелить себе в ногу
Чем ссылочные поля отличаются от полей-указателей?
bormand # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
Cnapmak # 0 ⇈
Pig # 0 ⇈
defecate-plusplus # 0 ⇈
bormand # 0 ⇈
defecate-plusplus # 0 ⇈
bormand # 0 ⇈
MAKAKA # 0 ⇈
?
Внутри main создает временный объект с 42, и должен бы по идее разрушиться сразу, но остается жить?
Кажется, до 11 такого не было, и надо было вручную делать
но это не точно.
MAKAKA # 0 ⇈
хотя пишут ворнинг
defecate-plusplus # 0 ⇈
в смысле не бывает
bormand # 0 ⇈
gost # 0 ⇈
UB. ССЗБ.
MAKAKA # 0 ⇈
В С++ же нет нулл сейфти, это же не котлин. Ты обязан проверить, что указатель не указывает на говно, прежде чем покласть его результат в ссылку
https://govnokod.ru/26958#comment575830
gost # 0 ⇈
MAKAKA # 0 ⇈
ну ты же понял, что имелось ввиду, не?
Когда я пишу
int& foo = *some_shit_that_returns_null()
там под капотом в foo оказывается адрес null, и при следующем обращении случается бугор
Я не спорю, что UB. Просто забавно, что оно как-бы заметено под ковёр из за сахара.
gost # 0 ⇈
В этом-то и дело. Багор случается сразу же, как только ты разыменовываешь nullptr. Просто его последствия начинают проявляться позже.
Перефразируя j123123 (https://govnokod.ru/26809#comment575323):
>>> Если ты в крестах используешь какую-то сраную ебучую хуйню, типа разыменования указателя, то ты сам дурак должен соблюдать предельную осторожность с этой хуйней, и вся ответственность за segmentation fault и прочие подобные спецэффекты лежат на тебе. И нехуй в этом винить ссылки
MAKAKA # 0 ⇈
Сразу случается UB, а багор случается чуть позже (хотя наверное может и сразу случиться в теории)
Я так понимаю, что именно это им не нравится.
3.14159265 # 0 ⇈
На как по мне это сахарок с ёбнутыми значками.
guest # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
Тяжелое бремя написания амперсанда ложится на плечи автора функции, а не на ее клиента
j123123 # 0 ⇈
Всё там бывает, надо просто уметь. https://wandbox.org/permlink/N8evr3fCGLXDwEMt
Эти ссылки - просто сахарок над указателями
guest # 0 ⇈
молодец, круто ты наебал тупого компилятора
j123123 # 0 ⇈
int *crap = (int *)malloc(100500);
на котором этот самый malloc обсирается и возвращает NULL, и потом в некую хуйню передается по ссылке crap[0]
и разыменование нулевой хуйни произойдет по факту не в том месте, где вызвана хуйня shit(crap[0]) а внутри самой функции shit(), которая с этой ссылкой будет что-то делать
MAKAKA # 0 ⇈
>и потом в некую хуйню передается по ссылке crap[0]
лол, то есть можно передать уже говно, и узнать о том, что ты передал говно через три часа в другом месте?
По сути у тебя будет ссылка на нул, да)
Проверил. Такая хуйня скомпилировалсь, и упала. Какой багор))))
j123123 # 0 ⇈
Типа да, при передаче по указателю ты можешь нормально проверить, что указатель там не NULL, а по ссылке - хуй там. Но NULL там быть все же может.
Ссылки - просто сахарок над указателями для заедушных питушков, чтоб поменьше * писать
MAKAKA # 0 ⇈
Если ты поклал в ссылку нул, то ты сам кривой.
В моем примере видимо надо так
j123123 # 0 ⇈
guest # 0 ⇈
Я не крестовичок, но так понимаю, что ссылки умнеьшают количество семантического мусора, и не заставляют клиента "знать" про ссылку.
Но как любая абстракция ссылка не бесплатна для мозга. Нужно понимать теперь что там происходит н а самом делде
j123123 # 0 ⇈
Можно, разрешаю. https://wandbox.org/permlink/edO6vo7o3ntWfZVJ
https://stackoverflow.com/a/9263728
MAKAKA # 0 ⇈
а ты грил нельзя на хуйню проверить
j123123 # 0 ⇈
Ну так действительно нельзя
Там будет такая же хуйня с варнингом на строчке if (&bar == NULL)
prog.cc:11:18: warning: the compiler can assume that the address of 'bar' will never be NULL [-Waddress]
MAKAKA # 0 ⇈
reference cannot be bound to dereferenced null pointer in well-defined c++ code
То есть катсинг-то сам по себе валиден (взять адрес того, на кого указывает ссылка), а вот проверка оного на нул -- варнинг
j123123 # 0 ⇈
Ну как бы да, компилятор имеет право считать, что раз у нас ссылка, то это точно что-то валидное, и NULL там быть не может.
MAKAKA # 0 ⇈
компилятор имеет полное право мою проверку выкинуть, и код упадет
gost # 0 ⇈
> *(int *)0
У тебя произошло UB, и что там дальше (да и раньше тоже) происходит — никого не волнует.
В well-formed программе на крестах nullptr в ссылке быть не может никогда.
j123123 # 0 ⇈
>> *(int *)0
>У тебя произошло UB
Если внимательно посмотреть, я использую особую опцию "-fno-delete-null-pointer-checks" от которой компилятор ложит хер на ту часть стандарта, которая запрещает разыменовывать NULL.
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
> -fdelete-null-pointer-checks
>
> Assume that programs cannot safely dereference null pointers, and that no code or data element resides at address zero. This option enables simple constant folding optimizations at all optimization levels. In addition, other optimization passes in GCC use this flag to control global dataflow analyses that eliminate useless checks for null pointers; these assume that a memory access to address zero always results in a trap, so that if a pointer is checked after it has already been dereferenced, it cannot be null.
>
> Note however that in some environments this assumption is not true. Use -fno-delete-null-pointer-checks to disable this optimization for programs that depend on that behavior.
>
> This option is enabled by default on most targets. On Nios II ELF, it defaults to off. On AVR, CR16, and MSP430, this option is completely disabled.
>
> Passes that use the dataflow information are enabled independently at different optimization levels.
Но видимо этот флаг не запрещает компилятору предполагать, что ссылка не может быть с NULL.
gost # 0 ⇈
j123123 # 0 ⇈
Надо просто ввести новую опцию -fallow-null-in-references
gost # 0 ⇈
…то ты пишешь не на «C++», а на другом языке. С тем же успехом я могу ругать сишные структуры за какие-то багры в «Cython».
> где прочитать или записать хуйню по нулевому указателю вполне может иметь смысл
По Стандарту, кстати, никакого «нулевого» указателя не существует. Конкретный адрес nullptr и NULL выбирает платформа. Синтаксис «T * ptr = 0;» является синтаксическим сахаром:
§ 7.3.11/1 (N4842)
Именно поэтому читать-записывать по нулевому адресу тебе никто* не мешает:
* При условии, что там лежит валидный объект.
j123123 # 0 ⇈
Только вот тогда получается так, что на настоящем «C++» не пишет вообще никто, т.к. ни один компилятор крестоговна на данный момент не реализует стандарт на 100%
j123123 # 0 ⇈
https://modern-sql.com/standard/levels
> The SQL standard is huge. More than 4300 pages in its SQL:2016 incarnation. No single implementation can ever implement all features.0 Even in the early releases, such as SQL-92, the SQL standard defined different conformance levels so that vendors can claim conformance to a subset of the standard.
Почему кстати в стандарт крестоговна не ввели эти «conformance levels»? По-моему вполне логичный шаг.
gost # 0 ⇈
Desktop # 0 ⇈
ведь компилятор C++ не должен отвечать за другие языки.
в чём тут подвох
gost # 0 ⇈
Desktop # 0 ⇈
если у него реально другой язык, почему крестовый компилятор успешно компилирует такие исходники?
может, проблема просто в обилии UB'ов?
gost # 0 ⇈
Термин — да, поведение — нет.
Как только в твоей программе случается UB — она перестаёт быть валидной программой на «C++», для которой Стандарт определяет какое-либо поведение.
> почему крестовый компилятор успешно компилирует такие исходники?
Потому что для программы с UB крестовый компилятор может делать что угодно!
> может, проблема просто в обилии UB'ов?
Это совершенно другая проблема.
Desktop # 0 ⇈
то есть компилятор C++ может взять код не на C++ и скомпилировать из него какую-то ебалу
хорошо, что я на таком не пишу
bormand # 0 ⇈
gost # 0 ⇈
Как, впрочем, и няшная сишка: там тоже есть UB и оно точно так же может через карман укусить за яйца. С другой стороны, в §J.2 (N2346) приведён полный список сишных UB, так что их можно более-менее заучить и не допускать. С третьем стороны, этот список занимает десять страниц A4.
bormand # 0 ⇈
Емнип, там офигенные вещи были в духе "название хедера не должно начинаться с цифры". Вот назовёшь хедер 1.h и получишь UB.
Desktop # 0 ⇈
ломалось бы на этапе линковки или даже раньше
guest # 0 ⇈
Доказать это не всегда можно.
Представь, что ты слинковался с библок petuh.dyld, и написал
как ты сможешь доказать, что в рантайме у тебя в петуха не положится ссылка на нул?
bormand # 0 ⇈
guest # 0 ⇈
bormand # 0 ⇈
Ну либо вместо голого указателя возвращать какой-нибудь non_null_ptr<T>. Или ссылку, лол.
guest # 0 ⇈
>non_null_ptr
ого
я не знал про такую хуню
bormand # 0 ⇈
Я её выдумал. Но пишется за пару минут. В конструкторе проверишь, что не нулл и бросишь исключение. А дальше можно таскать без проверок и потерь пирфоманса.
guest # 0 ⇈
bormand # 0 ⇈
Ну по-хорошему да. Не верить же автору сторонней либы на слово? Тем более сишные либы так сигналят об ошибке и тебе один хер проверять. А в крестах тебе голый указатель не так уж часто возвращают.
gost # 0 ⇈
Если ты уверен, что get_petuhz() тебе никогда не вернёт nullptr — можешь делать так безо всяких проверок. В этом и есть смысл крестов (да и няшной тоже): ты можешь делать «опасные» операции безо всяких проверок, если считаешь, что они всегда будут корректны.
Однако если твоя уверенность тебя подведёт и get_petuhz() таки вернёт nullptr — ты получишь UB, и дальше твоя программа может делать абсолютно что угодно.
MAPTbIwKA # 0 ⇈
А потому что только Программист знает, что валидно, а что нет.
Он царь и бог, а не житель анально огороженной крепости с надсмотрщиком как в джава
rotoeb # 0 ⇈
а я придерживаюсь тех же взглядов. Компилятор/интерпретатор должен только проверять корректность синтаксиса, и никак не обучать тебя каким-то типизациям и, тем более, заставлять тебя удалять неиспользуемые переменные (как в "Go").
bormand # 0 ⇈
rotoeb # 0 ⇈
Так даёт-то это что?
guest # 0 ⇈
я вот не сделал delete, и все скомпилировалось.
На всякий случай напомню, что ты отвечаешь конардо. Не стоит вступать с ним в серьезную техническую дискуссию:)
bormand # 0 ⇈
Pig # 0 ⇈
Desktop # 0 ⇈
библиотека это уже бинарь
guest # 0 ⇈
j123123 # 0 ⇈
Текст стандарта крестоговна написан на английском и не является строго формализованным описанием, так что там еще хуй поймешь, можно над каким-то пунктом рассуждать как жиды над торой, что там говностандартизаторы в этом пункте имели в виду. Надо написать четкую формальную спецификацию, чтоб никаких разночтений не было, потом уже говорить, что можно писать на каком-то мифическом «C++»
gost # 0 ⇈
> Надо написать четкую формальную спецификацию
Написали. Называется «Стандарт».
> разночтений
Приведи реальный пример разночтений в Стандарте.
j123123 # 0 ⇈
Это не четкая формальная спецификация. Это текстовая человекочитаемая хуйня на естественном языке, которую можно по-разному понять и проинтерпретировать своим мозгом.
> Приведи реальный пример разночтений в Стандарте.
Могу привести реальный пример, когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать
gost # 0 ⇈
> Могу привести реальный пример
Ну приведи.
j123123 # 0 ⇈
> Давайте с memcpy, с ним проще. Я смотрю по C++17 draft, но для простоты и тех, кто не хочет грузить 1500-страничные пдфки, даю ссылки на онлайн-версию, где стандарт уже немного другой.
> Так вот, 6.8/2 и /3 говорят, что вы можете делать memcpy для объектов trivially copyable типов (в частности, если они не являются подобъектами), даже если они не содержат валидного значения. И как мы видим из 11.2/1, наличие конструктора по умолчанию никак не влияет на свойство trivially copyable.
> Надеюсь, этого достаточно, чтобы разобраться с memcpy.
> А вот с memset всё интереснее. Он в стандарте упоминается всего несколько раз, и все эти разы — без описания семантики. Поэтому вопрос о том, что разрешено делать с memset, является совсем неочевидным. Ответ «memset в коде на плюсах использовать нельзя вообще», похоже, стандарту не противоречит.
И в ответе:
> Ну в самом же деле, нельзя же ожидать, чтобы в стандарте были перечислены вообще все допустимые случаи использования любых комбинаций функций из стандартной библиотеки.
Какой багор )))
Поэтому я за «Brainfuck».
gost # 0 ⇈
§ 21.5.3/1 (N4842)
Идём в «C standard», читаем:
(N2346)
Всё, никаких разночтений.
j123123 # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
O_o
gost # 0 ⇈
Какой багор )))
j123123 # 0 ⇈
j123123 # 0 ⇈
Надо четко написать, что такие-то функции ведут себя точно так же, как ведут себя функции Си такого-то стандарта. А что такое meaning какого-то хеадера сишки? Просто определение функций, а что они делает - хуй знает. Это вам не крестоговно, когда там какие-то шаблоны с кодом запилены.
gost # 0 ⇈
>>> The memset function copies the value of c (converted to an unsigned char) into each of the first n characters of the object pointed to by s.
Тут разве что приебаться можно к «first n characters of the object pointed to by s», но это нужно хорошенько задрочить крестовый object representation или как его, а там дохуя листов A4 формального английского, который нашему отделу чтения и парсинга обрабатывать лень.
j123123 # 0 ⇈
contents - содержимое. Там содержатся какие-то определения функций. Т.е. инклудя <cstring> мы инклудим то же, что и в <string.h>
meaning - значение. Ну т.е. смысл того что заинклужено. А смысл в хедере там такой, что вот такие-то функции есть, которые принимают такие-то аргументы и возвращает такую-то хуйню. Хедер сам по себе не описывает то, что конкретно какая функция делает. Так что надо четко сказать, что функии, определенные в таком-то хедере, делают то же самое, что они делают в сишечке такого-то стандарта.
gost # 0 ⇈
На самом деле хорошая приёбка, но, тем не менее, Стандарт может противостоять даже таким дотошным людям!
§ 2/2
> Ну может это означает что-то в духе
Всё есть в Стандарте.
> когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать
И тем не менее, после качественной раскопки Стандарта разночтений выявлено всё ещё не было. Отсутствие строгого определения слова «meaning» полностью компенсируется примечанием 1.
MAKAKA # 0 ⇈
gost # 0 ⇈
j123123 # 0 ⇈
Научная фантастика и научная реальность в информатике
Эдсгер В. Дейкстра
...
Чуть раньше я упомянул плохую документацию системы как внутреннее ограничение надежности, с которой система может быть использована механически в более широком контексте. Теперь самое время указать, что привлечение технического писателя редко является выходом из положения; в сущности, это не более как признание того, что разработчики системы в некотором роде функционально безграмотны. Обычно даже целая армия технических писателей не может справиться с задачей, поскольку система становится столь сложной, что не поддается точному описанию.
j123123 # 0 ⇈
guest # 0 ⇈
https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
В сраном JS их 800
Myxa # 0 ⇈
guest # 0 ⇈
Myxa # 0 ⇈
guest # 0 ⇈
bootcamp_dropout # 0 ⇈
guest # 0 ⇈
bootcamp_dropout # 0 ⇈
MAKAKA # 0 ⇈
Если бы в браузер была встроена ада, то все бы на ней писали, и текли, и не жужжали, и меньше было бы в мире undefined, Nan и [Object object].
Потому что статическая типизация позволяет отловить больше ошибок на уровне комплияции. Это же очевидно. Именно потому MS изобрёл TS.
bootcamp_dropout # 0 ⇈
это означает что бандл у меня поделен на файлы, файлы подгружаются асинхронно, для работы сайта в первую секунду нужен один, а все остальные догружаются в течении минуты, а какие-то через 10 минут
при этом в коде файлы считают друг друга модулями
как это реализовать на компилируемых языках?
rotoeb # 0 ⇈
Хуяндл.
Myxa # 0 ⇈
bootcamp_dropout # 0 ⇈
меня наебали?
Myxa # 0 ⇈
Ось сразу посылает нахуй, если DLL указана в таблице импорта. Но этот способ далеко не единственный.
Второй способ — вызов функций LoadLibrary и GetProcAddress. Этим способом можно подгрузить DLL в любой момент и не упасть, если она не загрузится.
А в «Линуксе» есть dlopen.
bootcamp_dropout # 0 ⇈
bormand # 0 ⇈
А если на помойке нашёл - ну подизасмишь.
bootcamp_dropout # 0 ⇈
как мне метод позвать или функцию?
bormand # 0 ⇈
bootcamp_dropout # 0 ⇈
guest # 0 ⇈
В отличие от js, тебе нужно знать сигнатуры функций и структуры, чтобы скомпилироваться.
Потому дефлорацию выносят в хедер и дают клиенту.
И пока джаваскриптер пытается понять какие параметры получает функция продираясь через документацию, чуваки из сишки посто жмут хотки в IDE, и текут
bootcamp_dropout # 0 ⇈
bormand # 0 ⇈
Опыт и везение. Что ещё защищает сишника?
rotoeb # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
bootcamp_dropout # 0 ⇈
gost # 0 ⇈
gost # 0 ⇈
guest # 0 ⇈
Myxa # 0 ⇈
guest # 0 ⇈
грубо говоря у тебя есть .h, там описана сигнатура функции Petuh.
Ты знаешь, что в .dll есть функция с такой сигнатурой и таким именем, и берешь ее оттуда.
Если ты ошибся, ну тут пиздец.
Но так же ты моещь и в JS ошибиться, и в Java
просто последствия будут куда более предсказуемые
Myxa # 0 ⇈
Myxa # 0 ⇈
Список символов получить можно. А вот семантику параметров функций нужно знать. В JS ты же тоже не знаешь, для чего какой аргумент у функции из чужого скрипта.
bormand # 0 ⇈
Как что-то плохое. Немного дизасмишь саму длл, немного дизасмишь или дебажишь проги, которые ее юзали.
Если там не дичь какая-то, то часто удаётся понять суть аргументов.
Myxa # 0 ⇈
Малость дизасмишь проги, которые её юзали.
Много примеров использования получаешь.
Это в нашей чеховской-кибальчеховской все-все знают.
guest # 0 ⇈
guest # 0 ⇈
А чтобы понять семантику нужно или смотреть как ее вызывают (как сказал броманд) или читать асм. Но это вообще для суперскиловых чуваков, которые живут одновременно с Олькой и Идой
bormand # 0 ⇈
MAKAKA # 0 ⇈
или время запуска?
bormand # 0 ⇈
Myxa # 0 ⇈
MAKAKA # 0 ⇈
guest # 0 ⇈
я не за пхп
3.14159265 # 0 ⇈
j123123 так мастерски доёбуется до С++, что из него вышел бы отличный кретостандартизатор.
j123123 # 0 ⇈
gost # 0 ⇈
Ну так там это и написано. Для каждого хедера из стандартной либы (что крестов, что няшной) есть отдельный раздел, в котором описываются meaning соответствующих функций.
В крестовом Стандарте в описании <cstring> даже ссылка есть на соответствующий пункт няшного («See also: ISO C 7.24»).
j123123 # 0 ⇈
Там же про meaning хедера говорится, а не про meaning функций.
Ну и вот мы тут как раз еще один пример получили, когда обсуждают, что именно вот конкретно этот говнопункт в крестостандарте значит, и как его надо понимать, как ты и просил в https://govnokod.ru/26958#comment575919
> даже ссылка есть на соответствующий пункт няшного («See also: ISO C 7.24»).
Мало ли что это может значить? Ну может это означает что-то в духе "ну вот может ну нахуй это крестоговно, вот посмотрите лучше стандарт сишки, там прикольней написано".
3.14159265 # 0 ⇈
Какая однозначность )))
j123123 # 0 ⇈
> int value_at_zero = *(int *)(1 - 1);
Тут кстати можно не согласиться.
Если хуйня «(1 - 1)» после вычислений дает то же, что и дает NULL (допустим если в хедере есть «#define NULL 0», и при этом из курса школьной математики нам известно, что «1-1=0»), то получим UB (даже если там валидный объект). Если «*(int *)(1 - 1)» дает ту же хуйню, что и «*(int *)nullptr» - получем ту же UB хуйню (даже если там валидный объект)
gost # 0 ⇈
В этом и весь смысл: (1 - 1) и 0 в контексте нулевого указателя — это разные вещи. Простой нолик-литерал — это синтаксический сахар, к нулевому адресу не имеющий никакого отношения. Поэтому из NULL == 0 вовсе не следует, что (int *)(1 - 1) — это нулевой указатель.
> Если «*(int *)(1 - 1)» дает ту же хуйню, что и «*(int *)nullptr» - получем ту же UB хуйню
А так будет только тогда, когда компилятор считает нулевой адрес за nullptr. Очевидно, если на какой-то платформе нулевой адрес валиден, то компилятор nullptr в него раскрывать не будет. Ну, если его не лалки анскильные писали, конечно.
bormand # 0 ⇈
gost # 0 ⇈
Myxa # 0 ⇈
bormand # 0 ⇈
Какой нуллптр )))
Myxa # 0 ⇈
guest # 0 ⇈
а где в стандарте про это читнутьб?
gost # 0 ⇈
>>> There was a strong consensus among the CWG that only the literal 0 should be considered a null pointer constant, not any arbitrary zero-valued constant expression as is currently specified.
Причём до C++11 нулевым указателем считалась любое нулевое константное выражение, что приводило к такому багру:
guest # 0 ⇈
выходиц, так нельзя
const int i = 0;
int* b = i;
//а так льзя
int* i = 0;
int* b = i;
лл
guest # 0 ⇈
Myxa # 0 ⇈
guest # 0 ⇈
j123123 # 0 ⇈
Есть реальные примеры, где это были б разные вещи?
https://wandbox.org/permlink/awAHb63ePcdv8Jal - я что-то не нашел.
bormand # 0 ⇈
j123123 # 0 ⇈
bormand # 0 ⇈
guest # 0 ⇈
никак?
bormand # 0 ⇈
guest # 0 ⇈
не буду я под такие платформы писать
j123123 # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
>>> A null pointer constant is an integer literal (5.13.2) with value zero
Ну и https://wg21.cmeerw.net/cwg/issue903 ещё.
j123123 # 0 ⇈
в крестах может вывести "sosnoole!\n" ?
Ну и хуйня ваши кресты.
gost # 0 ⇈
> Ну и хуйня ваши кресты.
Ну а как ещё соблюсти два условия:
1) Иметь «нулевой» указатель nullptr, который на текущей платформе всегда будет невалиден;
2) Иметь возможность писать в любые адреса, поддерживаемые платформой, включая 0.
?
j123123 # 0 ⇈
В теории можно изобрести такую платформу, где абсолютно все указатели будут валидны, так что это условие по-сути своей - хуйня полная.
> 2) Иметь возможность писать в любые адреса, поддерживаемые платформой, включая 0.
Это можно было б решить какой-нибудь нестандартной хуйней, например специальным оператором разыменования или встроенной функцией, которая подразумевает что через нее можно можно и нулл разыменовать, и нихуя плохого в этом нет. Типа вместо
int hui = *(* int )0;
делаем
int hui = __buildtin_superduper_dereference((* int )0);
gost # 0 ⇈
А на практике такая платформа нахуй не нужна.
Нулевой указатель нам нужен не для того, чтобы UB генерировать, а чтобы на него, внезапно, проверять. Вот есть у нас malloc(), она нам может вернуть либо указатель на выделенную память, либо nullptr/NULL в случае, если что-то пошло не так. Если у нас все указатели валидны — мы сосём хуй.
> специальным оператором разыменования
Ну и плодим никому не нужные сущности. Вместо этого разумнее было бы лишние сущности удалить, и за нулевой указатель считать только платформозависимый NULL/nullptr. Тогда мы спокойно можем писать по любому валидному числовому адресу, и никаких багров не возникает.
guest # 0 ⇈
тогда
#define NULL 0xFFF....
а вот что делать с 0 -- хэзэ
gost # 0 ⇈
Разумеется.
guest # 0 ⇈
int* a = 0; //будет совсем не 0, правильно?
и проверка if(foo == 0) тоже не 0?
bormand # 0 ⇈
guest # 0 ⇈
если это поинтер, то на NULL
азазаза, какой можно багорчик ловить лютый.
if (a == getFoo()) { //если getFoo это функция, то 0.
// А если переделать в макрос компайл тайма, то 0 превратица в NULL?
}
gost # 0 ⇈
§ 7.3.14/1 (N4842)
bormand # 0 ⇈
Какой багор))
guest # 0 ⇈
gost # 0 ⇈
gost # 0 ⇈
В текущих крестах — да, реальный адрес будет 0xFFF….
> if(foo == 0)
0 неявно скастится к уко-ко-козателю и всё будет работать правильно.
j123123 # 0 ⇈
Эта хуйня без NULL-питухов решается - в malloc просто возвращаем структуру, которая состоит из bool и из поинтера. Если в буле false то значит malloc обосрался с выделением памяти, если в буле true то значит все норм, и из другого члена этот поинтер читаем и чето с ним делаем.
gost # 0 ⇈
Только вот есть проблема: обычно размер указателя равен размеру регистра, поэтому твоя структурка в [er]?ax не поместится. Как результат — придётся на каждый вызов любой функции, потенциально возвращающей NULL, лишний раз дрочить память, а это пиздец пирфомансу.
guest # 0 ⇈
переписывать будет не быстро
j123123 # 0 ⇈
gost # 0 ⇈
j123123 # 0 ⇈
На практике нахуй не нужны языки, которые указывают, какие платформы нужны, а какие нет.
Если взять например 8-bit AVR говноконтроллеры и почитать memory map из даташита, то там на нулевых адресах хранятся значения регистров, т.е. регистры можно прочитать из памяти таким вот образом. Если используется malloc() хуйня, то конечно же она в регистрах нихуя выделять не должна, так что для обозначения того, что malloc() обосрался, вполне можно использовать адрес 0x0000, и для этого не надо никакой хуйни с гарантировано невалидными адресами, которые разыменовывать нельзя, достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
gost # 0 ⇈
И шо, все остальные адреса валидные? Прямо от 0 до 0xFFF…?
> достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
Ок, хочу функцию
И чтобы она на тех контроллерах, на которых маппинг регистров в память поддерживается, возвращала мне этот адрес, а на тех, где не поддерживается — об этом сообщала. Вызывать её будем триллион раз в час.
j123123 # 0 ⇈
Ну вот тут https://scienceprog.com/avr-microcontroller-memory-map/ написано что начиная с RAMEND+1 адреса идет External RAM вплоть до 0xFFFF. Если ее реально всю дозаполнить реальной памятью, то тогда похоже что да, все адреса там так или иначе будут за что-то отвечать.
>чтобы она на тех контроллерах, на которых маппинг регистров в память поддерживается, возвращала мне этот адрес, а на тех, где не поддерживается — об этом сообщала.
А нахуя? Почему б тебе не узнать о неподдерживаемости на этапе компиляции (или на этапе чтения даташитов на конкретный говноконтроллер)?
gost # 0 ⇈
Принимается. Да, у 16-битных (и меньше) контроллеров с лишней памятью проблемы. Их владельцам можно посоветовать либо использовать компилятор, производитель которого явно задекларировал, что в нём обращаться к NULL можно, либо хуярить асмовставки, благо из них обращаться к любым адресам никто не запрещает.
> А нахуя? Почему б тебе не узнать о неподдерживаемости на этапе компиляции (или на этапе чтения даташитов на конкретный говноконтроллер)?
Потому что надо.
Ну а вообще я к тому, что вот это:
>> достаточно просто адресов, которые никакая хуйня вернуть при нормальных условиях как валидное значение указателя не должна.
— плохое, неконсистентное решение. Если я могу прочитать данные по какому-то указателю, то почему он должен считаться невалидным?
guest # 0 ⇈
j123123 # 0 ⇈
А зачем для этого считать (void *)0 не тем же самым, что и (void *)(1-1) ? Ну пусть бы был какой-то nullptr который на одной платформе равен какому-нибудь 0xFFFFFFFF, на второй равен 0xDEADC0DE, на какой-то другой - еще какой-то хуйне, зачем его синонимировать с литералом 0? Чтоб с сишкой была совместимость?
bormand # 0 ⇈
В крестах же NULLа не было в отличие от сишки.
gost # 0 ⇈
«GCC» Стандарт понимает правильно и выдаёт вышеуказанные ошибки. А вот «Visual Studio» последней версии на них кладёт болт и успешно компилирует все три примера. Какой багор )))
gost # 0 ⇈
«GCC» всё делает правильно и выводит «Pointer!/Pointer!/.../...»: https://wandbox.org/permlink/5HqRbFjgqNgUraDk.
А вот «Visual Studio» анскильно выдаёт четыре «Pointer!»: https://gcc.godbolt.org/z/W8hdY7 (cout заменил на няшный puts, а то там пиздец килобайты асма вылезли). Какой багорище )))
bormand # 0 ⇈
Даже если у тебя какая-то платформа, где нулл можно юзать, ну положи туда какую-то структуру, на которую ты никогда не будешь брать указатели, которые могут быть невалидными. Ту же таблицу прерываний. Всяко что-то такое у тебя есть.
И не надо портить платформу и городить костыли на ровном месте.
И явный UB про разадресацию nullptr тоже можно убрать. Он ничем не отличается от любого другого указателя на мусор.
gost # 0 ⇈
Какие костыли-то? Отдельный NULL/nullptr без привязки к конкретным числам — вполне себе заебись решение.
> И UB про разадресацию nullptr тоже можно убрать.
UB нельзя убирать, UB — это священная корова оптимизации!
bormand # 0 ⇈
А UB про "специальное значение", имхо, пользы не приносит. Только вред и уязвимости в духе выбрасывания проверки на нулл потому что я уже обратился.
guest # 0 ⇈
Пусть бы в коде 0 всегда был nullptr, а если железно это не так, то лучше починить это в платформе
Всё таки 0 != NULL очень сильно повышает требования к скилььности прогера
bormand # 0 ⇈
Таблица прерываний, загрузочный код и т.п.
Т.е. к нулю вроде и есть обращения, но их буквально пара штук на всю ось и они никогда не содержат проверку на нулл.
gost # 0 ⇈
Зачем? Зачем?
Где тут повышения требования к скилльности прогера?
guest # 0 ⇈
int i = 0;
int* q = (int*)i; //вот что тут будет?
if (q == NULL) //а тут что?
Я понимаю, что так кастить нельзя наверное (особенно из инта) но всё таки есть код, который уже так написан, и я до сегодняшнего дня не думал, что он может не работать
gost # 0 ⇈
Дык в любом языке с nullable ссылками дошли до того, что неплохо бы иметь специальное значение для пустой ссылки.
> int* q = (int*)i; //вот что тут будет?
С принудительным кастом — указатель на адрес 0.
> if (q == NULL) //а тут что?
Зависит от платформы.
Проблема не в принудительном касте, проблема в неявном. По-хорошему, надо было полностью запретить неявные касты из любых чисел в указатели. Хочешь инициализировать указатель пустым значением — пиши «ptr = NULL», а не выёбывайся с «ptr = 0».
Но, разумеется, теперь Боржоми пить поздно, совместимость с сишкой выкинуть не получится.
guest # 0 ⇈
Это правда. Но далеко не в любом языке можно make pointer from integer without cast)
>С принудительным кастом — указатель на адрес 0.
а без него на NULL?
>Зависит от платформы.
ну да, от того равен ли NULL нолю.
>Проблема не в принудительном касте, проблема в неявном.
да, согласне
>а не выёбывайся с «ptr = 0»
было бы хорошо
Именно потому я за паскаль)
gost # 0 ⇈
А без него, к счастью, не скомпилится даже сейчас.
guest # 0 ⇈
в няшной скомпилица
gost # 0 ⇈
guest # 0 ⇈
gost # 0 ⇈
Дык NULL — это по определению невалидный адрес.
> в духе выбрасывания проверки на нулл потому что я уже обратился
Дык уязвимость-то будет не в выбрасывании проверки на нулл, а в самом обращении. После обращения к указателю проверка на нулл полностью бессмыслена.
bormand # 0 ⇈
Скажем так, это просто адрес, который не может быть выделен аллокатором, описанным в стандарте (ну и не может принадлежать локалке и т.п.) Поэтому я его могу юзать как маркер пустоты или как маркер ошибки. И это удобно для всяких структур данных.
Но он, имхо, ничуть не более невалидный, чем указатель на какой-нибудь ROM или MMIO, который я тоже по стандарту получить и юзать не могу, лол.
Зачем его делать пиздец-пиздец невалидным и особенным - я х.з.
gost # 0 ⇈
Дык он и никакой не особенный. Обращение к нему — точно такое же UB, как и обращение к любому другому невалидному адресу.
>> В код по ошибке просочилось чтение.
>> А дальше пошло исполнение кода.
Какое исполнение-то? Чтение тебе кинуло SIGINT и всё, привет.
bormand # 0 ⇈
На то и UB. Невалидный согласно стандарту адрес вполне может быть физически валидным.
bormand # 0 ⇈
Почему нулл то в этом плане особенный? Потому что весь код засрали проверками на него, а теперь тормозит?
gost # 0 ⇈
А какие ещё адреса согласно Стандарту невалидны?
> Почему нулл то в этом плане особенный?
Потому что компилятор не знает и знать никак не может, какие адреса у тебя там валидные, а какие нет.
Откуда компилятор должен узнать, что по 0x1234 у тебя ничего валидного не лежит?
bormand # 0 ⇈
bormand # 0 ⇈
В код по ошибке просочилось чтение. Дальше была проверка, которая остановила бы код. Но гцц ее выкинул. А дальше пошло исполнение кода.
Обращение к *p не должно создавать факт "p не нулл", имхо.
gost # 0 ⇈
§ 9.3.3.2/5 (N4842)
Так что жаловаться на null в ссылках — это как сделать строку без \0 в конце, а потом ругать «strlen()» за то, что она падает.
bormand # 0 ⇈
gost # 0 ⇈
> и устроить true == false
Кстати, в прошлом году на ГК это обсуждали: делали memcpy() в буль-буль переменную и наблюдали за весёлыми эффектами на разных компиляторах. Кажется, там ещё какой-то конпелятор проверял чётность буль-буля и 2 считал за false.
guest # 0
YpaHeLI_ # 0 ⇈
Присвоишь ты в это поле ссылку на объект в другом скопе, он уничтожится и получишь SEGFAULT, и будешь потом долго искать в чем дело, а найдя будешь переписывать свой монолит.
> по твоему поля всегда должны копироваться чтоли?
умные указатели, RAII, а не это уж точно.
gost # 0 ⇈
, кроме того, что ссылки тебе гарантируют null-safety?
MAKAKA # 0 ⇈
А ссылку не можешь (точнее можешь, но компилятор может такую проверку выкинуть, бо будет считать, что она всегда фолс))
Но я не защищаю эту позицию. Я не крестовик, но мне тоже нравится null safety. Во всяком случае в джавах и котлинах мне нравится знать, что поле никогда не может быть нулом, и не проверять его каждый раз, как дурак
gost # 0 ⇈
> Во всяком случае в джавах и котлинах мне нравится знать, что поле никогда не может быть нулом, и не проверять его каждый раз, как дурак
Подтверждаю.
Кстати, если уж развивать мысль — в «Ко-ко» же можно какой-нибудь грязной рефлексией в поле типа T записать null?
bormand # 0 ⇈
guest # 0 ⇈
ТС вообще не нравится, что ссылка не влияет на время жизни объекта, и ты должен сам вручную вот это всё.
В коко можно записать рефлексией.
А еще можно дернуть метод джавы, про который не известно нулл он или нет.
А еще можно написать "!!"
Вполне можно NPE получить при определенных навыках)
guest # 0 ⇈
123 123
Неужели трудно запомнить?
Как твой пароль, только 2 раза.
MAKAKA # 0 ⇈
MAKAKA # 0 ⇈
bormand # 0 ⇈
MAKAKA # 0 ⇈
наплодили шлюхоаккаунтов, ну шо за люди, блять...
guest # 0 ⇈
хрюкни
MAKAKA # 0 ⇈
ну на
ХРЮЮЮЮ
guest # 0 ⇈
guest # 0 ⇈
MAKAKA # 0 ⇈
С ссылками и поинтерами вообще такая проблема есть в крестах, угу.
>умные указатели
Ну так используй умные указатели в полях, это же можно наверное?
gost # 0 ⇈
Умные указатели нужны тогда, когда наш класс владеет объектом (за исключением std::weak_ptr, но это специфическая штука). А когда класс должен ссылаться на какой-то объект, очевидно, приходится использовать либо указатели (и ловить багры от nullptr), либо ссылки (и ловить багры от невозможности изменить объект, на который указывает ссылка).
MAKAKA # 0 ⇈
bormand # 0 ⇈
YpaHeLI_ # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
bormand # 0 ⇈
gost # 0 ⇈
> Для данного класса какой-нибудь unique вполне сойдёт.
А вот не факт. Я, может, не хочу ебать кучу, а хочу
.
bormand # 0 ⇈
MAKAKA # 0 ⇈
Десктоп, было такое?
правда что именно там было на стеке яне помню
bormand # 0 ⇈
Тогда всегда пишешь как для кучи, а конпелятор сам разберётся.
Жабий жит вроде умеет такое. Кресты пока нет, но собираются добавить в стандарт возможность выпиливать пару new/delete.
MAKAKA # 0 ⇈
потому что иначе был бы ад: яхочу передать структуру из двух интов (например Point), и должен в кучу срать?
нувот джит умеет доказать, что ссылка не утекает и вот
bormand # 0 ⇈
MAKAKA # 0 ⇈
типа я такой сру в кучу, а он ESP вертит
bormand # 0 ⇈
3.14159265 # 0 ⇈
Апгрейд мув-семантики?
Они ещё предлагают похожую технику, если конструктор+деструктор тривиальный, то объект можно копировать через memcpy.
Особенно поможет стд::вектору, чтобы при удвоениях делать realloc.
Desktop # 0 ⇈
gost # 0 ⇈
>>> А, ну да, это ж кресты, тут думать надо.[/color]
j123123 # 0 ⇈
>думать надо.
C++ — довольно таки примитивное, но монстровое поделие, полное исторически сложившихся нелепых нагромождений. Человек, который хорошо в нем ориентируется — это хорошее зубрилко, а не хороший программист. Умение героически преодолевать трудности, которые создает твой собственный инструмент, вместо того, чтобы решать непосредственно прикладную задачу, в современном мире ценится разве что только среди прыщавых сосок. Работодатель же это сомнительное умение не ценит, и совершенно справедливо.
guest # 0
Аккаунт MAKAKA был взломан хакером (кажется, инью). Возможно, он использовал Meltdown уязвимость моего процессора, или тот факт, что пароль от аккаунта был 123, но тем не менее этот аккаунт более мне не принадлежит.
guest # 0 ⇈
MAKAKA # 0 ⇈
gost # 0 ⇈
MAKAKA # 0 ⇈
MAPTbIwKA # 0 ⇈
блять
как ты мог насоздавать фаек с детским паролем, ты ж не уёбок
MAKAKA # 0 ⇈
Ты вот кладешь телефон на работе на стол? Как ты знаешь, что его не спиздят?
Pig # 0 ⇈
MAPTbIwKA # 0 ⇈
и машину всегда лочу
нахуй надо
bormand # 0 ⇈
Даже когда один дома?
MAPTbIwKA # 0 ⇈
bormand # 0 ⇈
MAPTbIwKA # 0 ⇈
зато пароль у меня не 123
bormand # 0 ⇈
Ну вот зачем ты выдал инфу о своём пароле? Теперь на 1 вариант меньше перебирать.
MAPTbIwKA # 0 ⇈
раки набрутили пароли со старых древних акков и время от времени с них срут
набрутили потому, что пароли там типа 123
Макака каждый раз, когда начинают срать, первым кричит, что "опять эти раки"
но всем файкам поставил именно 123 в качестве пароля
наверное, чтобы ракам было через пару лет удобнее набрутить ещё учёток
bormand # 0 ⇈
guest # 0 ⇈
bootcamp_dropout # 0 ⇈
guest # 0 ⇈
guest # 0 ⇈
gost # 0 ⇈
3oJIoTou_xyu # 0 ⇈
guest # 0
именно по этому я против "SQL"
guest # 0
Начиная с 20 сентября AppStore, Google Play и другие должны будут удалить китайские приложения из соображений нацбезопасности, следует из заявления Министерства торговли США, опубликованном на сайте.
guest # 0 ⇈
bormand # 0 ⇈