abbra: (Default)
abbra ([personal profile] abbra) wrote2012-07-11 12:33 pm

Клеймо на всю жизнь

Не хотите больше быть программистом? Оставьте свой след в истории:
http://blog.8thlight.com/dariusz-pasciak/2012/07/03/dereferencing-null-pointer-without-a-seg-fault.html

После того, как прочитали, заходите под кат и ответьте на вопрос: Скажите, а вас учили, что оператор -> над классами в C++ эквивалентен разыменованию указателя в C?

Что интересно, в стандарте С++ в 5.2.5 (Class member access) в третьем абзаце написано:
If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of 5.2.5 will address only the first option (dot).

Правда, 13.5.6 (Class member access) говорит уже более аккуратно об этом:
An expression x->m is interpreted as (x.operator->())->m for a class object x of type T if T::operator->() exists and if the operator is selected as the best match function by the overload resolution mechanism (13.3)

[identity profile] arkanoid.livejournal.com 2012-07-11 09:53 am (UTC)(link)
holy shit!
tobotras: (Default)

[personal profile] tobotras 2012-07-11 10:00 am (UTC)(link)
Спасибо :)

[identity profile] beldmit.livejournal.com 2012-07-11 10:16 am (UTC)(link)
Я в свое время на похожее поведение уже натыкался.

http://beldmit.livejournal.com/51712.html?nc=6#comments

Оптимизация - страшная вещь.

[identity profile] b-a-t.livejournal.com 2012-07-11 10:19 am (UTC)(link)
А не (x.operator->()).m?

[identity profile] blacklion.livejournal.com 2012-07-11 10:20 am (UTC)(link)
Хм... Очередная ЕЖУПА. В смысле, то, что можно разыменовывать так NULL до тех пор пока в методе нет обращения (прямого или косвенного) к this я знаю не помню сколько лет...

[identity profile] blacklion.livejournal.com 2012-07-11 10:21 am (UTC)(link)
Это если этот оператор есть, о чём сообщает вторая цитата из стандарта. А если нету — просто разыменовать. А если метод не виртуальный (статическая линковка), то this не нужен. А если в методе нет обращения к виртуальным методам или не-статическим полям, то this по-прежнему не нужен и может быть любым мусором, в том числе и NULL. Всё логично, на самом деле.

[identity profile] poige.livejournal.com 2012-07-11 10:22 am (UTC)(link)
this будет 0, и всё. IIRC.

[identity profile] blacklion.livejournal.com 2012-07-11 10:22 am (UTC)(link)
Более того, если operatot->>() не будет трогать this, то тоже будет работать.

[identity profile] beldmit.livejournal.com 2012-07-11 10:33 am (UTC)(link)
Вероятно, на практике компиляторы нарушают этот пункт стандарта - потому что шанс, что будет именно описанное поведение, достаточно высок.

[identity profile] blacklion.livejournal.com 2012-07-11 10:35 am (UTC)(link)
Ааа, я тебя не так понял, прошу прощения :)

[identity profile] arkanoid.livejournal.com 2012-07-11 11:06 am (UTC)(link)
ну я тоже не знал. но я никогда и не претендовал на знание плюсцов более, чем требуется, чтобы разобраться в чужой программе.

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

[identity profile] arkanoid.livejournal.com 2012-07-11 11:15 am (UTC)(link)
В данном случае я просто получил еще одно подтверждение того, что наука умеет много гитик, а сходство плюсцов с plain C в большинстве случаев не более, чем опасная кажимость.

[identity profile] b-a-t.livejournal.com 2012-07-11 11:35 am (UTC)(link)
Не понял, к чему ты это все. Про NULL все достаточно понятно и почти ожидаемо.

Мой вопрос был про то, что operator->() должон бы возвращать T* в общем случае, в результате чего выполнялось бы выражение из первого абзаца. А две стрелочки - почти рекурсия.

Впрочем, если возвращается указатель, то -> сводится к простому типу и произойдет то самое разыменовывыние (*X).m.

[identity profile] ihar hrachyshka (from livejournal.com) 2012-07-11 12:12 pm (UTC)(link)
Если у вас в программе есть хотя бы одно разыменование null-поинтера, вам никто не гарантирует вообще хоть какого-либо поведения (даже запуска функции main). Ибо undefined behavior, а "раз Бога нет, то все можно".

[identity profile] beldmit.livejournal.com 2012-07-11 12:13 pm (UTC)(link)
В моем случае было не разыменование, а вызов метода.

[identity profile] ihar hrachyshka (from livejournal.com) 2012-07-11 12:20 pm (UTC)(link)
[C++11: 5.2.5/2]: For the first option (dot) the first expression shall have complete class type. For the second option (arrow) the first expression shall have pointer to complete class type. The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of 5.2.5 will address only the first option (dot). In either case, the id-expression shall name a member of the class or of one of its base classes. [ Note: because the name of a class is inserted in its class scope (Clause 9), the name of a class is also considered a nested member of that class. —end note ] [ Note: 3.4.5 describes how names are looked up after the . and -> operators. —end note ]

[identity profile] youngracoon.livejournal.com 2012-07-11 03:54 pm (UTC)(link)
Так если бы он знал, что ошибается. Ошибиться может каждый. Хотя (не будучи гуру в C/C++) могу допустить, что это что-то вопиющее...

[identity profile] ilya-dogolazky.livejournal.com 2012-07-11 07:55 pm (UTC)(link)
Вот этот тоже хорош http://blog.8thlight.com/kevin-liddle/2012/05/22/be-a-relentless-programmer.html --- он "learned thought patterns", извиняюсь за выражение. Ну в общем не удивительно с такой-то страничкой http://www.8thlight.com/careers

[identity profile] luarvique.livejournal.com 2012-07-12 12:07 am (UTC)(link)
Дети, ну чисто дети. И на таком ацком серьезе обьясняют, много буков, коровы, ошейники, все дела...

Ему бы за студентами ошибки в большом проекте поискать - так он бы там и не такое нашел. Правда написать об этом 5 страниц без единого матерного слова не смог бы.

[identity profile] luarvique.livejournal.com 2012-07-12 12:08 am (UTC)(link)
Ну да. Для продвинуых x86-программеров, ECX=0 на входе в функцию член класса.

[identity profile] luarvique.livejournal.com 2012-07-12 12:10 am (UTC)(link)
Саш, народ массово не знает что после "new" следует "delete" делать, а ты про реализацию классов... Только расстреливать через "-Dnew=abort -Ddelete=nafig", да...

[identity profile] luarvique.livejournal.com 2012-07-12 12:45 am (UTC)(link)
Вот тут самое интересное. Обращаем особое внимание на инструментарий (спойлер: С++ там конечно нет).

к студентам не пущать

[identity profile] silpol.livejournal.com 2012-07-23 06:36 pm (UTC)(link)
он же сколько невинных душ искалечит.

не будучи гуру в C/C++ ...

[identity profile] silpol.livejournal.com 2012-07-23 06:40 pm (UTC)(link)
... главное запомнить что это два разных языка, с разными целями создания и архитектурой, поэтому набирая в команду человека, у которого в CV написано C/C++ через слэш, нужно быть крайне осторожным и щупать его на предмет понимания что это _дваразныхязыка_ которые нечистоплотные HR и хэдхантеры лепят в один кусок. Другими словами, C/C++ в CV - это такой сигнал-к-атаке-три-зеленых-свистка.

ресайклинг из гуд

[identity profile] silpol.livejournal.com 2012-07-23 06:42 pm (UTC)(link)
главное раздобыть списки выпускников и опубликовать как кандидатов на "страшне перо не в гусака" ;)

[identity profile] just-regged.livejournal.com 2012-08-18 08:31 am (UTC)(link)
Это где так происходит, простите?

Вообще, забыть сделать delete[] - это как-то более привычно.

А вообще, boost::smart_ptr спасает :)

[identity profile] just-regged.livejournal.com 2012-08-18 08:32 am (UTC)(link)
Фриков каких-то откопал, Саша :)

[identity profile] just-regged.livejournal.com 2012-08-18 04:17 pm (UTC)(link)
Та ни, рубисты - они все такие. Ну, или через одного, в лучшем случае.

Мы тут пытались как-то рубиста нанять себе, редмайн под наши нужды допиливать. Поскольку опыта собеседований именно по руби у нас мало, ну, мы им попробовали давать всякие задачки из обычных собеседований: на манипулирование структурами данных, на оценку сложности задач ну и т.п. В целом, у нас очень простые задачки. Результат в целом оказался восхитительным в своей мерзости. Особо талантливых мой товарищ-начальник R&D срубал вопросом "сколько будет 2^8", но это, конечно, он со зла.
А ведь люди вполне себе работают, сайты строчат, деньги за них получают. Им просто не нужны все эти "тонкости". И не одним им, кстати. У нас и C++-программисты (ну, ладно, C++-билдер-программисты) на собеседования приходили, не умея обход дерева организовать. И ничего, трудятся.

[identity profile] alexey tourbin (from livejournal.com) 2012-08-18 07:08 pm (UTC)(link)
Вызов невиртуального метода происходит, грубо говоря, по заранее известному адресу, только неявно передается первый аргумент this=NULL. В этом же примере, если "void milk()" заменить на "virtual void milk()", то будет segmentation fault, поскольку вызов метода через VMT пойдет через нулевой указатель. Цитирование стандартов - это немного буквоедство, надо просто представлять, как эта дрянь работает. :-)

[identity profile] ilya-dogolazky.livejournal.com 2012-08-28 06:55 am (UTC)(link)
я бы наверное ответил, что 2^8 будет 10

[identity profile] gineer.livejournal.com 2012-10-17 08:42 am (UTC)(link)
Тоже мне бином Ньютона. :))

Указатель на метод не является частью реализации объекта(структуры) класса.
Только если этот метод виртуальный и\или в нем была бы попытка обращения по this, были бы проблемы.
А так, такому удивлятся может только человек ни разу не видевший свой код в ассемблере\дебагере. :))