Использует нулевой указатель для вызова статического члена UB [duplicate]

Считаете ли вы, что вы создаете свой собственный шаблон EditorTemplate для лица, отправителя и получателя? EditorFor и DisplayFor ищут настраиваемый шаблон, соответствующий типу объекта.

Внутренний метод будет искать шаблон, соответствующий типу объекта. Затем он будет искать шаблон, соответствующий базовому классу, а затем по цепочке наследования.

21
задан Columbo 18 March 2016 в 12:43
поделиться

4 ответа

27
ответ дан Columbo 17 August 2018 в 12:03
поделиться

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

Это основная ошибка допущения.

Приложение: обратите внимание, что при наличии дефекта CWG ( # 315

Addendum: g0]), который закрывается как «согласованный» , а не , делающий вышеуказанный UB, он полагается на положительное закрытие другого дефекта CWG ( # 232 ), который по-прежнему активен, и, следовательно, ни один из них не добавлен к стандарту.

Позвольте мне привести часть комментария из Джеймса Макнеллиса к an ответьте на аналогичный вопрос переполнения стека:

Я не думаю, что дефект CWG 315 «закрыт», поскольку его присутствие на странице «закрытые проблемы» подразумевает. В обосновании говорится, что это должно быть разрешено, потому что «* p не является ошибкой, когда p равно null, если значение lvalue не преобразуется в значение r». Тем не менее, это зависит от концепции «пустой lvalue», которая является частью предлагаемой резолюции для дефекта CWG 232, но которая не была принята.

3
ответ дан Community 17 August 2018 в 12:03
поделиться
  • 1
    @Columbo: Теперь, если вы продемонстрируете, что эти резолюции когда-либо превратили его в стандарт, у вас будет точка. – Deduplicator 12 February 2015 в 18:15
  • 2
    @Columbo: Я добавил добавление к заметке Джеймса Макнеллиса, в котором разъясняется, почему ваш ответ не оспаривает, что это UB. – Johann Gerell 12 February 2015 в 20:11
  • 3
    Теперь это единственный правильный ответ. Стыдно, что я не могу его снова вернуть. – Deduplicator 13 February 2015 в 01:30
  • 4
    Есть ли причина, почему реализация качества должна когда-либо заботиться об экземпляре в этом сценарии? Я полагаю, что было бы справедливо предупредить, что код может сломаться разработчиками компилятора, которые гордятся поиском & quot; умный & quot; способы избежать того, чтобы их компиляторы делали что-либо, не предусмотренное Стандартом. С другой стороны, Стандарт определяет только «соответствующую» формулу. реализация, а не «реализация, полезность которой не подрывается тупостью»; тот факт, что какое-то конкретное поведение допустимо первым, не означает, что последнее может вести себя аналогичным образом. – supercat 14 July 2018 в 16:53

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

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

Итак, в d->fun(); компилятор использует указатель d только во время компиляции , чтобы понять, что вы обращаетесь к члену класса demo, а затем игнорируете его. Никакой код не испускается компилятором для разыменования указателя, поэтому факт, что он будет NULL во время выполнения, не имеет значения.

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

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

0
ответ дан Mike Nakis 17 August 2018 в 12:03
поделиться
  • 1
    Ваше предлагаемое изменение может сломать существующий код. template <class T> f(T &t) { t.g(); } struct StillWorking { void g() {} }; struct NowBroken { static void g(); } }; f(StillWorking()); f(NowBroken()); – Christian Hackl 12 February 2015 в 18:02
  • 2
    «Нельзя использовать ссылку на экземпляр для ссылки на статический член». Этот корабль проплыл долго, давным-давно. – T.C. 12 February 2015 в 18:04
  • 3
    P.S .: Я хотел написать пример с const& (моя не будет компилироваться в любом случае), но точка стоит. – Christian Hackl 12 February 2015 в 18:05
  • 4
    @ T.C. да, он отплыл, но не имею ли я права придерживаться мнения, что так никогда и не было? – Mike Nakis 12 February 2015 в 18:49
  • 5
    @ChristianHackl вы были бы удовлетворены, если бы я написал «Это должно было быть невозможно». вместо «Это должно быть невозможно». ? – Mike Nakis 12 February 2015 в 18:50

Из C ++ Draft Standard N3337:

9.4 Статические элементы

2 Элементы static класса X класса X могут ссылаться на использование expression-id expression X::s; нет необходимости использовать синтаксис доступа к члену класса (5.2.5) для ссылки на член static. Член static может ссылаться на использование синтаксиса доступа к члену класса, и в этом случае оценивается выражение объекта.

И в разделе об объектном выражении ...

5.2.5 Доступ к члену класса

4 Если объявлено, что E2 имеет тип «ссылка на T», тогда E1.E2 является lvalue; тип E1.E2 - T. В противном случае применяется одно из следующих правил.

- Если E2 является членом данных static, а тип E2 - T, то E1.E2 - значение l; выражение обозначает именованный член класса. Тип E1.E2 - T.

На основании последнего параграфа стандарта выражения:

  d->fun();
  std::cout << d->a;

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

4
ответ дан R Sahu 17 August 2018 в 12:03
поделиться
  • 1
    Где в этих цитатах разрешено d не указывать на какой-либо объект? – Deduplicator 12 February 2015 в 18:13
  • 2
    "Если E2 является статическим элементом данных ... выражение обозначает именованный элемент. & quot; Он говорит это прямо там, и это имеет смысл, потому что указатель совершенно не имеет значения. – Kenny Ostrom 12 February 2015 в 18:19
  • 3
    @KennyOstrom: я не вижу никакого мандата, чтобы игнорировать UB, вызванный выражением E1 в этой цитате, извините. – Deduplicator 12 February 2015 в 18:20
  • 4
    @Deduplicator Где в стандарте действительно говорится о разыменовании нулевого указателя, само по себе, is неопределенное поведение? – T.C. 12 February 2015 в 18:23
  • 5
    @RSahu LHS из . необходимо оценить, даже если он статичен, или g().f() может не оценить g(). – T.C. 12 February 2015 в 18:42
Другие вопросы по тегам:

Похожие вопросы: