LINUX.ORG.RU

Субботний C++ (как правильно сообщать о не успехе)

 


0

2

Продолжаю осваивать С++. И возник вопрос как сделать правильно следующую вещь…

Есть некий метод некоего объекта. Метод в случае успеха создает некий другой объект. Ну и естественно хочется возвращать его через return.

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

А вот как такое правильно делать in cpp-way?

Все классы и методы мои, могу написать что захочу. А вот какие варианты идейно верные?

★★★
Ответ на: комментарий от pavlick

Это был не совсем честный тест и я пропустил одну деталь.

Что в нём нечестного-то?

Причина вывода «not null» в том, что i не используется, и компилятор это чтение просто вырезает (но в if’e этого не понимают, ведут себя так, буд-то оно было).

Причина вывода «not null» в том, что поведение программы не определено из-за разыменования нулевого указателя. То есть может быть любым. Вообще. На этом можешь остановить свой поток рассуждений, потому что, например, завтра может выйти новая версия GCC или Clang, которая на такой код будет выдавать форматирование диска, если указатель равен NULL, и это всё ещё будет корректным поведением компилятора.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hateyoufeel

Причина вывода «not null» в том, что поведение программы не определено из-за разыменования нулевого указателя. То есть может быть любым. Вообще. На этом можешь остановить свой поток рассуждений, потому что, например, завтра может выйти новая версия GCC или Clang, которая на такой код будет выдавать форматирование диска, если указатель равен NULL, и это всё ещё будет корректным поведением компилятора.

Ой, ну вот этот вот бред про формат диска … ). ЮБ - почти всегда значит, что это отдано на откуп компилятору, он может оптимизировать, делать что хочет. Не, ну можно специально делать больно юзерам, как это делает шланг, а главное с такой оптимизации толку нет. Но лучше, конечно, прописать в стандарте - unspecified, чтобы шланг тоже начал делать так, как это наиболее приемлемо для программистов. Я это про обращение по нулевым указателям, нужно всегда читать память, а не пихать в регистры желаемый компилятором бред.

pavlick ★★
()
Последнее исправление: pavlick (всего исправлений: 1)
Ответ на: комментарий от pavlick

ЮБ - почти всегда значит, что это отдано на откуп компилятору, он может оптимизировать, делать что хочет.

Кто тебе такую лажу сказал? Ещё раз, для особо невнимательных повторю: термин undefined behaviour означает, что поведение программы не определено и может быть любым. Вообще совсем любым. Свои влажные фантазии оставь при себе.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Причина вывода «not null» в том, что поведение программы не определено из-за разыменования нулевого указателя. То есть может быть любым. Вообще.

любым быть не может. тетрис с разыменованием нулевого указателя не превратится в компилятор с++. тетрис этот просто свалится с вполне определенной диагностикой - access violation. о каком любом поведении идет речь?

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

alysnix ★★★
()
Ответ на: комментарий от hateyoufeel

Кто тебе такую лажу сказал? Ещё раз, для особо невнимательных повторю: термин undefined behaviour означает, что поведение программы не определено и может быть любым. Вообще совсем любым.

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

pavlick ★★
()
Ответ на: комментарий от pavlick

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

Мне, похоже, стоит начать брать деньги за чтение стандарта другим людям.

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf

Страница 5, пункт 3.27:

undefined behavior
behavior for which this document imposes no requirements

Тебе перевести? :)

Ты думаешь я специально нули дереференсю?

Да хрен тебя знает. Вдруг ты NULL-фетишист какой-нибудь. Обмажешься своими нуллами и ходишь потом по округе, детей пугаешь.

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

Код, который выдаёт шланг, выполняется согласно тому, что написано в стандарте. Если твои ожидания отличаются, то это твоя проблема.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 2)
Ответ на: комментарий от alysnix

любым быть не может. тетрис с разыменованием нулевого указателя не превратится в компилятор с++. тетрис этот просто свалится с вполне определенной диагностикой - access violation. о каком любом поведении идет речь?

Охлолже! Ну вон я выше пример кода привёл, в котором разыменование NULL есть, а access violation нет. Более того, разные компиляторы выдают разный код. Где теперь твой бог?

и хватит отсылать к стандарту с++ там нет ни слова об оптимизации и выкидывании ветвей с уб

Ты же сам процитировал C++ Reference. Ну и вон я выше Павлику процитировал кусок стандарта про UB, где написано, что поведение может быть любым и ограничений на это нет.

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

А если найду?

hateyoufeel ★★★★★
()
Ответ на: комментарий от pavlick

Ты думаешь я специально нули дереференсю? Нет, это просто потенциальная ошибка, которую можно легко ловить, если не играться в тупые, ненужные оптимизации как делает это шланг.

Компилятор этого не может знать. Вдруг ты пишешь «супер-оптимизированную» библиотеку, где каждый такт на счету, а входные данные (не нулевой ли указатель) проверяются один раз где-то выше (может даже не в этой библиотеке)? Откуда компилятору знать с какого уровня надо проверять?

Тут нет решения, кроме как проверять каждый раз, но на это сишники не пойдут под страхом смерти. Или вводить специальные типы для «ненулевых указателей». Ну или как сейчас: программист должен позаботиться о том, что неопределённого поведения нет.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Почему? Им нравится страдать?

По всей видимости. Ну а ещё можно смеяться над языками, которые «тормозят».

Справедливости ради, вариант «всегда всё проверять» тоже не всегда работает.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Справедливости ради, вариант «всегда всё проверять» тоже не всегда работает.

Вариантов, как это решить, на самом деле тьма. Можно сделать отдельный тип для ненулевых указателей (не удивлюсь, если для C++ есть библиотека с этим, вот например: https://github.com/microsoft/GSL/blob/main/include/gsl/pointers). Можно сделать пару новых операторов, который при разыменовании кидают исключение если там NULL. Можно добавить прагму, которая включает проверки в каком-то отдельном участке кода.

Просто C/C++ и нормальные решения проблем – это абсолютно несовместимые вещи. C/C++ – это про то, как сделать через жопу, чтобы всем было максимально больно. Ей богу, ректальный копромазохизм от мира программирования.

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 3)
Ответ на: комментарий от hateyoufeel

Ну так gsl::not_null - это и есть официально рекомендуемый путь на сегодня. Ты сам павлику уподобляешься, когда гонишь на язык.

Плюс, указатели вообще выбираются именно тогда когда нуль возможен, иначе ссылка. Тут, конечно, не хватает промежуточного типа - мутабельных ссылок, да оно по опыту нечасто надо, и тут и заходит not_null.

И вообще, плюсовых проблем встречал/делал достаточно, но чтоб разыменование нуля - это большая редкость. Разговоров больше.

anonymous
()
Ответ на: комментарий от hateyoufeel

Страница 5, пункт 3.27:

Еще раз - нет никакого «абсолютного» ЮБ, что вот поведение прям вообще пальцем в небо. Большая их часть - пространство компилятору для оптимизаций. Тут можно вспомнить про то, как MSVC не делает strict aliasing оптимизацию, делая ЮБ вполне определенными в рамках себя. Да и в том же ГЦЦ можно включать оптимизации поштучно. Понятно, что есть вещи, которые от компилятора не зависят, ALSR, например.

Да хрен тебя знает. Вдруг ты NULL-фетишист какой-нибудь. Обмажешься своими нуллами и ходишь потом по округе, детей пугаешь.

Ну маскируй ошибки, успехов могу лишь пожелать. А я лучше эту ошибку найду при помощи нормального компилятора без дерьмооптимизаций и исправлю, а твой код на ЮБ будет работать т.к. шланг выплюнул каку-то непотребную какашку (хоть она и малость быстрее, да) и хрен ты его обнаружишь, ибо шибко ЮБ-эксперт.

char f(int i) {
	if (i == 1)
		return *(char*)0;
	return 'f';
}

-O3 шланг:
        movb    $102, %al
        retq

-O3 ГЦЦ:
        cmpl    $1, %edi
        je      .L4
        movl    $102, %eax
        ret
.L4:
        movzbl  0, %eax
        ud2

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

pavlick ★★
()
Ответ на: комментарий от hateyoufeel

Вариантов, как это решить, на самом деле тьма. Можно сделать отдельный тип для ненулевых указателей (не удивлюсь, если для C++ есть библиотека с этим, вот например: https://github.com/microsoft/GSL/blob/main/include/gsl/pointers). Можно сделать пару новых операторов, который при разыменовании кидают исключение если там NULL. Можно добавить прагму, которая включает проверки в каком-то отдельном участке кода.

Жесть, велосипедист. Все есть и работает, тебе твои ЮБ шоры мешают.

pavlick ★★
()
Ответ на: комментарий от pavlick

Еще раз - нет никакого «абсолютного» ЮБ, что вот поведение прям вообще пальцем в небо

Это ты на простых примерах можешь так считать. А теперь сходи разберись, почему в проекте 20-летней давности на 500к строк что-то так почему-то неправильно выполняется.

Тут можно вспомнить про то, как MSVC не делает strict aliasing оптимизацию, делая ЮБ вполне определенными в рамках себя.

Потому что программисты на C не могут в strict aliasing в большинстве случаев. Большая часть линуксокода перестаёт работать, если его включить.

А я лучше эту ошибку найду при помощи нормального компилятора без дерьмооптимизаций и исправлю, а твой код на ЮБ будет работать т.к. шланг выплюнул каку-то непотребную какашку (хоть она и малость быстрее, да) и хрен ты его обнаружишь, ибо шибко ЮБ-эксперт.

$ cat null1.cc 
#include <iostream>

char f(int i) {
  if (i == 1)
    return *(char*)0;
  return 'f';
}

int main()
{
  std::cout << f(1) << std::endl;
}

$ clang++ null1.cc -o null -O2 -fsanitize=undefined
null1.cc:5:12: warning: indirection of non-volatile null pointer will be deleted, not trap [-Wnull-dereference]
    return *(char*)0;
           ^~~~~~~~~
null1.cc:5:12: note: consider using __builtin_trap() or qualifying pointer with 'volatile'
1 warning generated.

$ ./null 
null1.cc:5:12: runtime error: load of null pointer of type 'char'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior null1.cc:5:12 in 
f

Ах какой же шланг нехороший!

Но ГЦЦ поступает много умнее - дефолтно выбирает более надежный вариант, а особые гурманы доведут производительность до предела.

Ты реально упорный в отстаивании своего желания говнокодить.

Жесть, велосипедист. Все есть и работает, тебе твои ЮБ шоры мешают.

У тебя вот не работает :D

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 1)
Ответ на: комментарий от hateyoufeel

Ах какой шланг

Тьфу ты … Вы бы хоть погуглили для начала …

Владимир

anonymous
()
Ответ на: комментарий от hateyoufeel

indirection of non-volatile null pointer will be deleted, not trap [-Wnull-dereference]

да вот же флаг о котором я говорил пару постов назад! что он быть должен. и вразумительная диагностика - кусок будет удален.

и чего копья ломать? ответ на вопрос - …зачем его вообще удалять, остается на совести удаляющих…

alysnix ★★★
()
Ответ на: комментарий от hateyoufeel

Ладно, я все. Мнениями обменялись. Я никого не призываю на ЮБ писать, наооборот - предлагал избавляться от него используя нормальный компилятор без этих зашкварных оптимизаций (да шлангу тоже можно отключить 100%, но зря он так дефолтно на -O>0 делает, имхо).

pavlick ★★
()
Ответ на: комментарий от pavlick

Я никого не призываю на ЮБ писать, наооборот - предлагал избавляться от него используя нормальный компилятор без этих зашкварных оптимизаций (да шлангу тоже можно отключить 100%, но зря он так дефолтно на -O>0 делает, имхо).

Да, но зачем такой компилятор будет нужен? Программисты на C++ должны страдать по максимуму.

hateyoufeel ★★★★★
()
Ответ на: комментарий от alysnix

Ты написал быдлокод не по стандарту, компилятор насовал тебе за обе щеки, кончил на футболку и вытер член о занавески. Всё честно, это C.

anonymous
()
Ответ на: комментарий от anonymous

Ты написал быдлокод не по стандарту

а ты написал быдлокоммент, как бУдто ты с++ компилятор. ты может с ума сошел, не?

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Ты написал быдлокод не по стандарту

а ты написал быдлокоммент, как бУдто ты с++ компилятор. ты может с ума сошел, не?

Это анонимус. Учитывая сложность и количество кода в компиляторах C++, я не удивлюсь, если один из них наконец-то обрёл сознание и пишет на ЛОР. А, быть может, даже модерирует его!

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

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 2)
Ответ на: комментарий от hateyoufeel

или компилятором твоего любимого языка.

это питон у моей дочери взбесился. но я его не люблю. этот питон не понимает, что любой канонический супер идеальный код можно превратить в некорректный, просто удалив одну строку. неважно почему, кошка шла по клавиатуре, ребенок поиграл в твой комп и еще 100 вариантов.

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

alysnix ★★★
()
Ответ на: комментарий от alysnix

а ты написал быдлокоммент, как бУдто ты с++ компилятор. ты может с ума сошел, не?

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

anonymous
()
Ответ на: комментарий от alysnix

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

То ли дело C – вышел за границу массива и написал новую программу. Прямо в рантайме.

anonymous
()
Ответ на: комментарий от anonymous

Но ты можешь попытаться доказать обратное.

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

ты похоже код пишешь с своей башке, там же запускаешь и там же он у тебя падает.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от alysnix

Я понимаю что у тебя уже истерика начинается от осознания глубины своей профессиональной деградации, но все-таки попытайся понять одну простую вещь. Компилятор волен делать любые ассампшоны относительно UB. И он их будет делать. Просто чтобы тебя позлить.Ты будешь открывать все новые и новые способы как компилятор может тебя нагнуть и выкинуть твой код, уйти в бесконечный цикл или вызвать ОМОН чтобы выкопать труп твоей покойной бабушки и хорошенько его обоссать.

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

Подумай, нужно ли это тебе?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.