Re[3]: const reference nullptr
От: Кодт Россия  
Дата: 27.06.17 16:31
Оценка:
Здравствуйте, ομικρον, Вы писали:

К>>- ненулевой адрес базы/наследника при сдвиге базы (при работе с указателями создаётся специальный код, превращающий нуль в нуль; при работе со ссылками этих проверок нет)


ομι>Вроде как и для ссылок есть проверки. Правда, говорят, не во всех случаях
Автор: Кодт
Дата: 28.10.09
.


http://ideone.com/A1mFYA

Если компилятор сам догадается, что происходит разыменование нуля, он может нагенерить любую ахинею.
Если не догадается, то просто молча сделает сдвиг базы.
Перекуём баги на фичи!
Re[7]: const reference nullptr
От: IID Россия  
Дата: 11.07.17 18:40
Оценка: :)
Здравствуйте, Dair, Вы писали:

D>я уточню в офисе


D>Я проверю в коде. Чисто из любопытства. Завтра отпишусь.


Ай-яй.
Мне, конечно, неинтересно, но раз пообещал — выполняй
kalsarikännit
Re[2]: const reference nullptr
От: prezident.mira Россия  
Дата: 11.07.17 19:03
Оценка: -1
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Dair, Вы писали:


D>>Или это яркий пример так называемого говнокода, как мне и показалось с первого взгляда?


К>Без контекста непонятно, до какой степени это говнокод.

К>Но говнокод в любом случае, т.к. это эксплуатация неопределённого поведения.

А есть ли здесь UB? Т.к. просто применение оператора * к нулевому указателю UB не является (несмотря на широко распространённое поверие, что является). Т.е.
*(SomeClass*)nullptr;

это ещё не UB само по себе.

UB является инициализация ссылок с помощью нулевой ссылки, вроде
const SomeClass& ref = *(SomeClass*)nullptr;


А вот является ли UB просто возврат нулевой ссылки из функции?

UPD: нашёл сам: return является инициализацией. Значит UB.
Отредактировано 11.07.2017 19:15 prezident.mira . Предыдущая версия .
Re[8]: const reference nullptr
От: Dair Россия  
Дата: 11.07.17 19:23
Оценка: 1 (1)
Здравствуйте, IID, Вы писали:

D>>Я проверю в коде. Чисто из любопытства. Завтра отпишусь.

IID>Мне, конечно, неинтересно, но раз пообещал — выполняй

В самом деле, забыл.

Заглушка, метод переопределен во всех "реальных" дочерних классах.
Re[3]: const reference nullptr
От: uzhas Ниоткуда  
Дата: 12.07.17 08:27
Оценка:
Здравствуйте, prezident.mira, Вы писали:

PM>А есть ли здесь UB? Т.к. просто применение оператора * к нулевому указателю UB не является (несмотря на широко распространённое поверие, что является).


я придерживаюсь противоположной точки зрения. можно ознакомиться здесь: https://stackoverflow.com/questions/28573215/is-dereferencing-a-pointer-thats-equal-to-nullptr-undefined-behavior-by-the-sta
и в C и в C++ разыменование нулевого указателя — UB имхо
однако считаю, что стандарту следует быть более точным в формулировках относительно данного вопроса
Re[3]: const reference nullptr
От: uzhas Ниоткуда  
Дата: 12.07.17 08:32
Оценка:
Здравствуйте, prezident.mira, Вы писали:

PM>UPD: нашёл сам: return является инициализацией.


Re[4]: const reference nullptr
От: prezident.mira Россия  
Дата: 12.07.17 17:57
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, prezident.mira, Вы писали:


PM>>А есть ли здесь UB? Т.к. просто применение оператора * к нулевому указателю UB не является (несмотря на широко распространённое поверие, что является).


U>я придерживаюсь противоположной точки зрения. можно ознакомиться здесь: https://stackoverflow.com/questions/28573215/is-dereferencing-a-pointer-thats-equal-to-nullptr-undefined-behavior-by-the-sta

Я ознакомился со ссылкой. Notes from the October 2003 meeting: [...] We agreed that the approach in the standard seems okay: p = 0; *p; is not inherently an error.

U>и в C и в C++ разыменование нулевого указателя — UB имхо

К счастью, что есть UB — определяется стандартом, а не чьими-то имхами.
Re[4]: const reference nullptr
От: prezident.mira Россия  
Дата: 12.07.17 17:59
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, prezident.mira, Вы писали:


PM>>UPD: нашёл сам: return является инициализацией.


U>


Это типа ты не согласен?
Re[5]: const reference nullptr
От: N. I.  
Дата: 15.07.17 12:56
Оценка:
prezident.mira:

U>>и в C и в C++ разыменование нулевого указателя — UB имхо

PM>К счастью, что есть UB — определяется стандартом, а не чьими-то имхами.

Ну, и какое же behavior для вычисляющегося выражения вроде *(int*)nullptr определяется действующим стандартом C++?

C++14 [expr.unary.op]

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points.


(int*)nullptr не указывает на какой-либо объект, и, следовательно, результатом здесь не может быть "an lvalue referring to the object or function to which the expression points". Если результат выполнения этого выражения другой, то какой именно? Если описания поведения нет, то де-юре получаем не что иное, как undefined behavior:

C++14 [defns.undefined]

undefined behavior
behavior for which this International Standard imposes no requirements
[ Note: Undefined behavior may be expected when this International Standard omits any explicit definition of
behavior ....


Де-факто же *(int*)nullptr считается просто no-op, т.е. это один из тех случаев, когда следует руководствоваться _мнением_ отдельных представителей комитета по стандартизации, а не официальным правилам.

Можно привести ещё более интересный пример, где по правилам C++ undefined behavior возникает де-юре:

#include <cstdlib>

int main()
{
    void *p = std::malloc(sizeof(int));
    *(int *)p; // undefined behavior
    std::free(p);
}

Причина та же самая, что и в случае с нулевым указателем: по адресу p нет никаких объектов. Де-факто подразумевается, что такая конструкция должна работать примерно как если бы вызов std::malloc(sizeof(int)) создал неинициализированный объект типа int.
Re[6]: const reference nullptr
От: prezident.mira Россия  
Дата: 15.07.17 14:04
Оценка:
Здравствуйте, N. I., Вы писали:

NI>C++14 [expr.unary.op]

NI>

The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points.


NI>(int*)nullptr не указывает на какой-либо объект, и, следовательно, результатом здесь не может быть "an lvalue referring to the object or function to which the expression points". Если результат выполнения этого выражения другой, то какой именно? Если описания поведения нет, то де-юре получаем не что иное, как undefined behavior:


Скажите, тип указателя тут важен? Ну т.е. важно, получаем ли мы null pointer to int или на какой ещё тип? (incomplete types не рассматриваем).
Re[6]: const reference nullptr
От: prezident.mira Россия  
Дата: 15.07.17 14:20
Оценка:
Здравствуйте, N. I., Вы писали:

NI>Можно привести ещё более интересный пример, где по правилам C++ undefined behavior возникает де-юре:


NI>
#include <cstdlib>

NI>int main()
NI>{
NI>    void *p = std::malloc(sizeof(int));
NI>    *(int *)p; // undefined behavior
NI>    std::free(p);
NI>}

NI>Причина та же самая, что и в случае с нулевым указателем: по адресу p нет никаких объектов. Де-факто подразумевается, что такая конструкция должна работать примерно как если бы вызов std::malloc(sizeof(int)) создал неинициализированный объект типа int.

http://eel.is/c++draft/basic.life#6

Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor]. Otherwise, such a pointer refers to allocated storage ([basic.stc.dynamic.deallocation]), and using the pointer as if the pointer were of type void*, is well-defined. Indirection through such a pointer is permitted but the resulting lvalue may only be used in limited ways, as described below.


Если expression это lvalue, которое referring to/denoting объект — этот объект "существовать" или быть ещё каким-то образом "валидным" не обязан, кроме как в специально оговорённых случаях.
Следует различать "lvalue, denoting object" и сам "object".

Сюда же пункт 7 http://eel.is/c++draft/basic.life#7

Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see [class.cdtor]. Otherwise, such a glvalue refers to allocated storage ([basic.stc.dynamic.deallocation]), and using the properties of the glvalue that do not depend on its value is well-defined.

Отредактировано 15.07.2017 14:25 prezident.mira . Предыдущая версия .
Re[7]: const reference nullptr
От: N. I.  
Дата: 15.07.17 16:30
Оценка:
prezident.mira:

NI>>(int*)nullptr не указывает на какой-либо объект, и, следовательно, результатом здесь не может быть "an lvalue referring to the object or function to which the expression points". Если результат выполнения этого выражения другой, то какой именно? Если описания поведения нет, то де-юре получаем не что иное, как undefined behavior:


PM>Скажите, тип указателя тут важен? Ну т.е. важно, получаем ли мы null pointer to int или на какой ещё тип? (incomplete types не рассматриваем).


Если *(T *)nullptr вычисляется, будучи операндом typeid (что возможно только если T — полиморфный тип), то поведение является определённым: typeid должен бросить исключение — этот случай специально оговорён. В остальных случаях, если T — это object/function type, то насколько я вижу, при вычислении *(T *)nullptr де-юре получается undefined behavior.
Отредактировано 15.07.2017 16:39 N. I. . Предыдущая версия .
Re[7]: const reference nullptr
От: N. I.  
Дата: 15.07.17 16:32
Оценка:
prezident.mira:

PM>

PM>Before the lifetime of an object has started but after the storage which the object will occupy has been allocated


А если никаких попыток создать объект вообще не предпринимается, это относится к "Before the lifetime of an object has started" или нет? Без авторитетного толкователя это правило можно интерпретировать как хочешь. Впрочем, если пример заменить на

#include <stdlib.h>

struct X
{
    int n;
};

int main()
{
    X *p = (X *)malloc(sizeof(X));
    p->n = 1; // undefined behavior
    free(p);
}

то тут хоть как трактуй, получишь undefined behavior — либо из-за indirection, либо из-за попытки "to access a non-static data member or call a non-static member function of the object", что весьма доставляет, т.к. подобный код широко используется в C.
Отредактировано 15.07.2017 16:34 N. I. . Предыдущая версия .
Re[8]: const reference nullptr
От: prezident.mira Россия  
Дата: 16.07.17 00:18
Оценка:
Здравствуйте, N. I., Вы писали:

NI>prezident.mira:


NI>>>(int*)nullptr не указывает на какой-либо объект, и, следовательно, результатом здесь не может быть "an lvalue referring to the object or function to which the expression points". Если результат выполнения этого выражения другой, то какой именно? Если описания поведения нет, то де-юре получаем не что иное, как undefined behavior:


PM>>Скажите, тип указателя тут важен? Ну т.е. важно, получаем ли мы null pointer to int или на какой ещё тип? (incomplete types не рассматриваем).


NI>Если *(T *)nullptr вычисляется, будучи операндом typeid (что возможно только если T — полиморфный тип), то поведение является определённым: typeid должен бросить исключение — этот случай специально оговорён. В остальных случаях, если T — это object/function type, то насколько я вижу, при вычислении *(T *)nullptr де-юре получается undefined behavior.


Т.е. по-Вашему полиморфные объекты существуют по нулевому указателю.
Re[8]: const reference nullptr
От: prezident.mira Россия  
Дата: 16.07.17 00:51
Оценка:
Здравствуйте, N. I., Вы писали:

NI>prezident.mira:


PM>>

PM>>Before the lifetime of an object has started but after the storage which the object will occupy has been allocated


NI>А если никаких попыток создать объект вообще не предпринимается, это относится к "Before the lifetime of an object has started" или нет?


Это уже попытка придраться на пустом месте. Вам показали, что Вы не правы, Вам стало от этого неприятно и Вы теперь цепляетесь за соломинку.
Там всё ясно написано и оракулов, предсказывающих будущее, для описания текущего поведения стандарт не требует.

NI> Без авторитетного толкователя это правило можно интерпретировать как хочешь.


Да, я понял. Пока не прилетит Страуструп на голубом вертолёте и не скажет: "N.I.! INDIRECTION ЧЕРЕЗ НУЛЕВОЙ УКАЗАТЕЛЬ — ЭТО НЕ UB!" то Вы всё что угодно будете интерпретировать как Вам угодно, лишь бы показаться правым во что бы то ни стало.

А по факту http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#315 закрыто как NAD (Not A Defect), что значит, что

The working group has reached consensus that the issue is not a defect in the Standard. A Rationale statement describes the working group's reasoning.

и в Rationale у 315 написано

*p is not an error when p is null unless the lvalue is converted to an rvalue


NI> тут хоть как трактуй, получишь undefined behavior


Если трактовать как Вам угодно, то UB будет всё, что Вам угодно. А остальным стандарт говорит http://eel.is/c++draft/basic.life#1

The lifetime of an object or reference is a runtime property of the object or reference. An object is said to have non-vacuous initialization if it is of a class or aggregate type and it or one of its subobjects is initialized by a constructor other than a trivial default constructor. The lifetime of an object of type T begins when:

Т.е. тут не UB. Кстати, к предыдущему примеру кода с "UB" этот пункт стандарта тоже относится.

NI> что весьма доставляет, т.к. подобный код широко используется в C.


В C нет конструкторов, там lifetime начинается с обретением storage. И, как видно из приведённого выше пункта стандарта, C++ тут совместим с C в случае тривиальных конструкторов.
Отредактировано 16.07.2017 4:34 prezident.mira . Предыдущая версия . Еще …
Отредактировано 16.07.2017 4:33 prezident.mira . Предыдущая версия .
Re[9]: const reference nullptr
От: N. I.  
Дата: 16.07.17 09:13
Оценка:
prezident.mira:

NI>>Если *(T *)nullptr вычисляется, будучи операндом typeid (что возможно только если T — полиморфный тип), то поведение является определённым: typeid должен бросить исключение — этот случай специально оговорён. В остальных случаях, если T — это object/function type, то насколько я вижу, при вычислении *(T *)nullptr де-юре получается undefined behavior.


PM>Т.е. по-Вашему полиморфные объекты существуют по нулевому указателю.


Нет, это особый случай вычисления *(T *)nullptr из серии "игнорируйте, что мы писали вон там, и руководствуйтесь описанием поведения именно для данного случая". Утверждение, что для indirection "the result is an lvalue referring to the object or function to which the expression points" в данном случае, очевидно, является некорректным, но зато поведение всей конструкции typeid(*(T *)nullptr) в целом является документированным.
Re[9]: const reference nullptr
От: N. I.  
Дата: 16.07.17 09:23
Оценка: 4 (2)
prezident.mira:

NI>>А если никаких попыток создать объект вообще не предпринимается, это относится к "Before the lifetime of an object has started" или нет?


PM>Это уже попытка придраться на пустом месте. Вам показали, что Вы не правы, Вам стало от этого неприятно и Вы теперь цепляетесь за соломинку.

PM>Там всё ясно написано и оракулов, предсказывающих будущее, для описания текущего поведения стандарт не требует.

"Всё ясно" там может быть только тем, кто плохо представляет, как должны выглядеть строгие формальные правила. Не всякий указатель типа T*, указывающий на некую область памяти, где расположен объект типа T, может использоваться для доступа к этому объекту в течение его lifetime. В C++17 даже появилось специальное средство std::launder для "отмывания" указателей:

[ptr.launder]

struct X { const int n; };
X *p = new X{3};
const int a = p->n;
new (p) X{5}; // p does not point to new object (3.8)
// because X::n is const
const int b = p->n; // undefined behavior
const int c = std::launder(p)->n; // OK


То, что здесь помечено как undefined behavior — это не какое-то новшество C++17, в C++14 оно также подразумевается. Раз уж между объектом и указателем на него может быть такая хитрая связь, то почему бы не допустить, что в формулировке "Before the lifetime of an object has started" речь также идёт о какой-то привязке к объекту, который реально пытаются создать? Если мы не обязаны ничего создавать, то почему бы вместо этой галиматьи

Before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any pointer that represents the address of the storage location where the object will be or was located may be used but only in limited ways.


не использовать что-то вроде

Any pointer of type cv1 T* that represents the address of a storage location suitable to hold an object of type T, but does not point to any object of type cv2 T whose lifetime has started and not ended, may be used but only in limited ways.


NI>> Без авторитетного толкователя это правило можно интерпретировать как хочешь.


PM>Да, я понял. Пока не прилетит Страуструп на голубом вертолёте и не скажет: "N.I.! INDIRECTION ЧЕРЕЗ НУЛЕВОЙ УКАЗАТЕЛЬ — ЭТО НЕ UB!" то Вы всё что угодно будете интерпретировать как Вам угодно, лишь бы показаться правым во что бы то ни стало.


В таких вопросах я бы ему не стал доверять :-) Вот таким людям, как Майк Миллер, Йенс Маурер и Ричард Смит, я верю.

PM>А по факту http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#315 закрыто как NAD (Not A Defect), что значит, что

PM>

PM>The working group has reached consensus that the issue is not a defect in the Standard. A Rationale statement describes the working group's reasoning.


И что? CWG решила, что разыменование нулевого указателя должно быть разрешено, но официального (закреплённого в стандарте) описания поведения программы при таком разыменовании (кроме специального случая с typeid) по-прежнему нет.

NI>> тут хоть как трактуй, получишь undefined behavior


PM>Если трактовать как Вам угодно, то UB будет всё, что Вам угодно. А остальным стандарт говорит http://eel.is/c++draft/basic.life#1

PM>

PM>The lifetime of an object or reference is a runtime property of the object or reference. An object is said to have non-vacuous initialization if it is of a class or aggregate type and it or one of its subobjects is initialized by a constructor other than a trivial default constructor. The lifetime of an object of type T begins when:
PM>

    PM>
  • storage with the proper alignment and size for type T is obtained, and
    PM>
  • if the object has non-vacuous initialization, its initialization is complete,
    PM>


Кучка байтов из памяти не может просто так стать объектом. "An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed." Если ничто в стандарте не говорит, что в некоем storage у тебя создаётся какой-то объект, то о существовании там такого объекта говорить нельзя. malloc объектов не создаёт:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0137r1.html

Drafting note: this maintains the status quo that malloc alone is not sufficient to create an object.


PM>В C нет конструкторов, там lifetime начинается с обретением storage. И, как видно из приведённого выше пункта стандарта, C++ тут совместим с C в случае тривиальных конструкторов.


Этот пункт не имеет отношения к определению множества конструкций, которые в принципе способны создавать объекты. Похожий пример сравнительно недавно рассматривался на core рефлекторе комитета по стандартизации, вот часть обсуждения:

  Скрытый текст
Peter Dimov:
All C code in existence is dead, it just doesn't know it yet.

Bjarne Stroustrup:
Interesting. Any details? :-)

Peter Dimov:
Well as I already said,

   struct X
   {
       int a, b;
   };

   int main()
   {
       X* p = (X*)malloc( sizeof(X) );

       p->b = 1; // undefined behavior
   }


Richard Smith:
One of my main goals in writing P0137 was to clarify the existing language rules. We cannot know whether the language rules express our intent without knowledge or agreement of what the language rules even *are*. Prior to P0137, asking N language lawyers about the above example would have given you probably more than 2N different answers, due the the confused and self-contradictory wording around the description of objects and lifetime. It was never my intent to *stop* after P0137; rather, this was intended to be the starting point for refining the object model to the point where it guarantees some reasonable subset of the implementation details that users have been relying on, while not infringing too heavily on optimizability (that users have *also* been relying on).

Now we have a suitably precise framework in order to express questions such as the above and reason about their answers, we can think about exactly which cases we want to have defined behavior, and which cases we want to allow implementations to (let their users) choose between bug detection / optimization and supporting low-level memory manipulation. I'm generally of the opinion that we should require users to be explicit when doing the latter, but making exceptions for some grandfathered-in C compatibility cases should be considered.

For instance, I strongly believe the above example *should* be made to have defined behavior in C++. But no ISO C++ standard has ever guaranteed it to have defined behavior -- an implementation is, and always was, at liberty to claim that it violates [basic.lval]/8, because the user never started the lifetime of an 'int' object to store p->b.
Отредактировано 16.07.2017 9:54 N. I. . Предыдущая версия .
Re[10]: const reference nullptr
От: prezident.mira Россия  
Дата: 16.07.17 09:59
Оценка:
Здравствуйте, N. I., Вы писали:

NI>prezident.mira:


NI>>>Если *(T *)nullptr вычисляется, будучи операндом typeid (что возможно только если T — полиморфный тип), то поведение является определённым: typeid должен бросить исключение — этот случай специально оговорён. В остальных случаях, если T — это object/function type, то насколько я вижу, при вычислении *(T *)nullptr де-юре получается undefined behavior.


PM>>Т.е. по-Вашему полиморфные объекты существуют по нулевому указателю.


NI>Нет, это особый случай вычисления *(T *)nullptr из серии "игнорируйте, что мы писали вон там, и руководствуйтесь описанием поведения именно для данного случая".


Поведение выражения не может быть defined, если поведение подвыражений — undefined. В отличие от C, где про оператор взятия адреса явно сказано, что

If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted

про оператор typeid говорится, что

glvalue expression is obtained by applying the unary * operator to a pointer

typeid не отменяет вычисления подвыражения вида *p и, если бы оно само по себе приводило к UB, то всё выражение с ним, как и остальное поведение программы стало бы undefined.

Причина, по которой typeid оговаривает поведение, проста: про полиморфные объекты стандарт говорит

Some objects are polymorphic; the implementation generates information associated with
each such object that makes it possible to determine that object’s type during program execution. For other
objects, the interpretation of the values found therein is determined by the type of the expressions
used to access them.

Т.е. для определения типа полиморфного объекта может понадобиться обращение к его значению. И хотя indirection для нулевого указателя это не UB, но попытка чтения значения — UB. Поэтому typeid, применение которого к объекту полиморфного типа потенциально может привести к чтению значения, явно оговаривает, что в случае lvalue, полученного разыменованием нулевого указателя, его применение к UB не приведёт.

NI> Утверждение, что для indirection "the result is an lvalue referring to the object or function to which the expression points" в данном случае, очевидно, является некорректным


Оно является контринтуитивным. И проблема только в этом — в wording-е. По этому поводу открыт issue 232. Где видно, что в корректности indirection для нулевого указателя и указателя, ссылающегося на элемент за последним элементом массива сомнений нет. А нужно изменить wording для этих случаев.
Re[10]: const reference nullptr
От: prezident.mira Россия  
Дата: 16.07.17 10:36
Оценка:
Здравствуйте, N. I., Вы писали:

NI>И что? CWG решила, что разыменование нулевого указателя должно быть разрешено, но официального (закреплённого в стандарте) описания поведения программы при таком разыменовании (кроме специального случая с typeid) по-прежнему нет.


CWG решила, что дефекта в стандарте нет, поэтому менять в нём ничего не нужно. А что касается Вашего любимого правила "behavior for which this International Standard imposes no requirements" которое вы применяете как-то своеобразно, то результат применения унарного оператора * определён:

the expression to which it is applied shall be a pointer to an object type, or a pointer to a function type and the result is an lvalue referring to the object or function to which the expression points


Написано: "shall be a pointer to an object type,". Т.е. говорится про тип выражения.
Я бы понял Ваши постоянные отсылки к определению UB, если бы было сказано "shall be a pointer to an object,". Но такого требования нет. Про значения указателя ничего не сказано — значит валидно для всех значений. Или Вы, может быть, считаете, что пока для всех пар значений целых чисел в стандарте явно не будет определён результат сложения (если нет переполнения), то 1+1 будет приводить к UB?

Требования к входному выражению предъявлены, результат описан. А что описан контринтуитивным для некоторых значений wording-ом — это не мешает ему быть определённым.
Re[10]: const reference nullptr
От: prezident.mira Россия  
Дата: 16.07.17 11:04
Оценка:
Здравствуйте, N. I., Вы писали:

NI>"Всё ясно" там может быть только тем, кто плохо представляет, как должны выглядеть строгие формальные правила.


Ок. Результат вычисления 1+1 это UB, пока в стандарте строго не сказано что это 2.

NI>Кучка байтов из памяти не может просто так стать объектом. "An object is created by a definition (3.1), by a new-expression (5.3.4) or by the implementation (12.2) when needed."


Да. Выделили malloc-ом "storage with the proper alignment and size for type T" и, если тип "have non-vacuous initialization", вызвали конструктор с использованием placement new. Всё соответствует тому, что вы процитировали и http://eel.is/c++draft/basic.life#1

NI> malloc объектов не создаёт:

NI>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0137r1.html
NI>

Drafting note: this maintains the status quo that malloc alone is not sufficient to create an object.


Я уже не в первый раз замечаю, что Вы не особо чистоплотны в методах ведения дискуссии. Либо просто не умеете читать.
Написано "malloc alone is not sufficient to create an object" — "только malloc-а недостаточно для создания [всякого] объекта".
Вы это подменили на "malloc объектов не создаёт". Чего в этой фразе не говорится.
Да, malloc-а недостаточно для создания всякого объекта, т.к. для некоторых типов кроме выделения стораджа может быть необходимо вызвать нетривиальный конструктор. См. http://eel.is/c++draft/basic.life#1 опять же.

PM>>В C нет конструкторов, там lifetime начинается с обретением storage. И, как видно из приведённого выше пункта стандарта, C++ тут совместим с C в случае тривиальных конструкторов.


NI>Этот пункт не имеет отношения к определению множества конструкций, которые в принципе способны создавать объекты. Похожий пример сравнительно недавно рассматривался на core рефлекторе комитета по стандартизации, вот часть обсуждения:


Больше похоже на то, что участники забыли про существование http://eel.is/c++draft/basic.life#1
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.