powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / virtual methods
25 сообщений из 356, страница 8 из 15
virtual methods
    #39652933
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestrdb_devпропущено...
Давай-ка я перевормулирую поточнееДавай просто возьмём формулировку из стандарта. Это будет самой точной формулировкой, по определению. И мучаться, выдумывать что-то не надо.Давай ка ты сейчас не заглядывая в текст стандарта процитируешь его слово в слово?
...
Рейтинг: 0 / 0
virtual methods
    #39652934
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Barlonerdb_devпропущено...
Угу!
Осталось объяснить это тем, кто пишет boost, компиляторы машинных кодов, потроха операционных систем, драйверы и прочим оптимизаторам.Ну-ка покажите пример из boost/потрохов операционных систем, который с точки зрения стандарта С++ приводил бы к UB...Вот более очевидный пример:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
   //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
   //!   For a non-empty vector, data() == &front().
   //!
   //! <b>Throws</b>: Nothing.
   //!
   //! <b>Complexity</b>: Constant.
   T* data() BOOST_NOEXCEPT_OR_NOTHROW
   { return this->priv_raw_begin(); }

Хоть буст и говорит, что "[data(),data() + size()) is a valid range" с точки зрения стандарта это мало что значит.
Вот такое, например
Код: plaintext
1.
2.
T* d = vec.data();
f(T[m]); // при условии size() > 1 и 1 <= m < size()


UB.

Конечно, UB как бы в пользовательском коде, т.к. он делает недопустимые операции. Но смысл в том, что переписать boost так, чтобы в использующем его коде не было UB — невозможно в принципе . Поэтому можно сказать, что UB в бусте.
...
Рейтинг: 0 / 0
virtual methods
    #39652935
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestЯ так понял, ты обиделся и перешёл на личности.Неа! На что тут обижаться? На то, что ты тычешь мне в нос текст стандарта, который не способен заучить наизусть? Да брось! :) Людей, способных запомнить весь текст стандарта слово в слово во всём мире по пальцам сосчитать.
Я не переходил на личности, а продемонстрировал разный подход к прохождению обучения в принципе, а не конкретно по отношению к кому-то.
...
Рейтинг: 0 / 0
virtual methods
    #39652937
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestДаже если в векторе, скажем, 5 элементов, доступ к третьему элементу с таким определением оператора[] как в бусте скорее всего приведёт к UB.
Еще раз. Не будет UB.
Даже если, как вы привели в том втором примере, каждый элемент вектора создавался отдельно через placement new, и "Никакого массива из int-ов в буфере нет. " .
Потому что согласно стандарту expr[i] эквивалентно *(expr + i), и никакой массив тут и не требуется. Достаточно чтобы там, по вычисленному адресу, который разыменовывается, был валидный объект, и он там есть.
А вот это ваше " т.к. индексация == адресная арифметика, а она определена только в пределах массива. " - вообще ни на чем не основано. Нет такого ограничения.
...
Рейтинг: 0 / 0
virtual methods
    #39652938
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestBasil A. Sidorov, ладно, объясняю на пальцах.

Пусть тип элемента вектора T = int.

Вот есть у нас кусок памяти под 4 элемента (для простоты — статический массив):
Код: plaintext
1.
unsigned char buffer[4*sizeof(int)];



Пусть в векторе 3 элемента 5, 10, 33. Их вектор создал с помощью placement new:
Код: plaintext
1.
2.
3.
new (buffer + 0*sizeof(int)) int {5};
new (buffer + 1*sizeof(int)) int {10};
new (buffer + 2*sizeof(int)) int {33};



Теперь что примерно делает оператор[]? Вот это
Код: plaintext
1.
2.
3.
4.
int& operator[](size_t n)
{
    return reinterpret_cast<int*>(buffer)[n];
}


А это точно приведёт к UB для n == 2, т.к. индексация == адресная арифметика, а она определена только в пределах массива. Никакого массива из int-ов в буфере нет.
Нет здесь никакого UB ни при buffer[2], ни при buffer[3], ни даже при buffer[15], так как массив типа unsigned char создан на 16 элементов и каждый следующий buffer[n+1] это следующий unsigned char, а не int. Конечно, ты можешь инициализировать этот массив как тебе заблагорассудится!
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
  unsigned char buffer[sizeof(int)<<2];
  
  int* p = (int*)buffer;
  *(p++) = 0x33323130; *(p++) = 0x37363534; *(p++) = 0x3b3a3938;
  unsigned char* c = buffer;
  for (int i = 0; i < sizeof(buffer); i++)
  {
    printf("buffer[%i] = '%c'; *c = '%c'\r\n", i, (char)buffer[i], *(c++));
  }
...
Рейтинг: 0 / 0
virtual methods
    #39652940
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestrdb_devНу так одним из частных случаев prvalue и есть нереферальный результат lvalue-to-rvalueМы обсуждали value category оператора *.Мы обсуждали взятие адреса - &
BarloneНу разработчики компилятора могут себе такое позволить в исходниках rtl, идущей в комплекте с конкретной версией компилятора. Потому что если в следующей версии компилятора поведение изменится, вместе с компилятором перепишут и rtl.
Да, реально видел такое в системных заголовках:
Код: plaintext
1.
#define offsetof(stype, member)  (size_t)&(((stype *)0)->member)


С точки зрения стандарта, разыменование нулевого указателя - UB. Но разработчик компилятора знает, что в данной конкретной версии так можно. А в следующей минорной версии там может оказаться
Код: plaintext
1.
#define offsetof(stype, member)  __builtin_offsetof(stype, member)

Так что в прикладном коде такие трюки нельзя, если конечно не прибивать гвоздями к конкретному релизу конкретного компилятора, потому что такое может сломаться при любом обновлении.
...
Рейтинг: 0 / 0
virtual methods
    #39652941
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyПотому что согласно стандарту expr[i] эквивалентно *(expr + i), и никакой массив тут и не требуется.См. цитату из стандарта ниже.
http://eel.is/c draft/expr.add#4 When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand.
If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i+j] if 0≤i+j≤n; otherwise, the behavior is undefined. Likewise, the expression P - J points to the (possibly-hypothetical) element x[i−j] if 0≤i−j≤n; otherwise, the behavior is undefined.
Anatoly MoskovskyДостаточно чтобы там, по вычисленному адресу, который разыменовывается, был валидный объект, и он там есть.А вот это ваше "достаточно, чтобы там, по вычисленному адресу, который разыменовывается, был валидный объект" — вообще ни на чём не основано. Нет такого разрешения.
Anatoly MoskovskyА вот это ваше " т.к. индексация == адресная арифметика, а она определена только в пределах массива. " - вообще ни на чем не основано. Нет такого ограничения.См. цитату из стандарта выше.
...
Рейтинг: 0 / 0
virtual methods
    #39652942
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestAnatoly MoskovskyПотому что согласно стандарту expr[i] эквивалентно *(expr + i), и никакой массив тут и не требуется.См. цитату из стандарта ниже.
http://eel.is/c draft/expr.add#4When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand.
If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i+j] if 0≤i+j≤n; otherwise, the behavior is undefined. Likewise, the expression P - J points to the (possibly-hypothetical) element x[i−j] if 0≤i−j≤n; otherwise, the behavior is undefined.И? :)
Откомпилируй это: 21455918 и наслаждайся!
...
Рейтинг: 0 / 0
virtual methods
    #39652943
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rdb_deva guestпропущено...
Мы обсуждали value category оператора *.Мы обсуждали взятие адреса - & Я объяснил, из каких соображений в комитете считают применение оператора * к нулевому указателю UB.
И ты полез рассказывать, что это применение не приводит к чтению объекта. И предлагать свои определения для lvalue.

1. Ты правда считаешь, что никто (в комитете и вне его) не знает, что применение оператора * не приводит к доступу к объекту и нужно всех упорно просвещать?
2. Если хочешь сделать код не UB переопределяя lvalue, лучше сделать это в виде предложения в стандарт, а не обижаться тут на форуме.
...
Рейтинг: 0 / 0
virtual methods
    #39652944
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
http://eel.is/c draft/expr.add#4If the expression P points to element x[i] of an array object x with n elements ...
Этот пункт стандарта относится к массивам. А вы сами сказали, что "Никакого массива из int-ов в буфере нет. "
Зачем на него ссылаетесь?
...
Рейтинг: 0 / 0
virtual methods
    #39652945
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rdb_devОткомпилируй это: 21455918 и наслаждайся!Пардон, не та ссылка.
Вот правильная: 21455915
...
Рейтинг: 0 / 0
virtual methods
    #39652946
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky http://eel.is/c draft/expr.add#4If the expression P points to element x[i] of an array object x with n elements ...
Этот пункт стандарта относится к массивам. А вы сами сказали, что "Никакого массива из int-ов в буфере нет. "
Зачем на него ссылаетесь? Затем, что дальше написано, что otherwise behavior is undefined.
Массива нет — значит при адресной арифметике получается UB.

Вроде вопрос был откуда я взял что там UB и откуда требование про массив. Я ответил. Или опять не ясно?
...
Рейтинг: 0 / 0
virtual methods
    #39652947
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly Moskovsky http://eel.is/c draft/expr.add#4If the expression P points to element x[i] of an array object x with n elements ...
Этот пункт стандарта относится к массивам.Этот пункт стандарта относится к арифметике указателей. А других-то пунктов и нет =)
...
Рейтинг: 0 / 0
virtual methods
    #39652948
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestrdb_devМы обсуждали взятие адреса - & Я объяснил, из каких соображений в комитете считают применение оператора * к нулевому указателю UB.
И ты полез рассказывать, что это применение не приводит к чтению объекта. И предлагать свои определения для lvalue.Что за бред?! Дашь ссылку на комментарий, где я изрёк подобную бредятину?
Смотри сюда: 21455820
rdb_deva guestКакой объект обозначает это lvalue, если оно применено к нулевому указателю?Какой тип указателя используешь, такой объект там и будет подразумеваться компилятором.
Что у нас там в далёком прошлом под DOS'ом располагалось в самом начале адресного пространства процессора Intel 8086? Таблица векторов прерываний (функций BIOS и DOS вызываемых машинной командой int)?
А что располагается сейчас в адресном пространстве пользовательского процесса Windows? 64кБ read-only памяти, каждый байт, которой, проинициализирован значением 0x00?Достаточно аргументированно?
...
Рейтинг: 0 / 0
virtual methods
    #39652949
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rdb_deva guestпропущено...
Я объяснил, из каких соображений в комитете считают применение оператора * к нулевому указателю UB.
И ты полез рассказывать, что это применение не приводит к чтению объекта. И предлагать свои определения для lvalue.Что за бред?! Дашь ссылку на комментарий, где я изрёк подобную бредятину? 21455748
Или в " И никакого доступа, приводящего к UB " под "доступом" не имелась в виду попытка чтения из объекта?
...
Рейтинг: 0 / 0
virtual methods
    #39652950
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestЭтот пункт стандарта относится к массивам.Этот пункт стандарта относится к арифметике указателей. А других-то пунктов и нет =)[/quot]Просто загляни в "legacy" - в стандарт ANSI C и внимательно изучи что такое массив и как работает арифметика типизированных указателей.
...
Рейтинг: 0 / 0
virtual methods
    #39652951
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rdb_deva guestЭтот пункт стандарта относится к массивам.Этот пункт стандарта относится к арифметике указателей. А других-то пунктов и нет =)Просто загляни в "legacy" - в стандарт ANSI C и внимательно изучи что такое массив и как работает арифметика типизированных указателей.[/quot]
А при чём тут стандарт C, если обсуждается стандарт C++? Впрочем, в стандарте C то же самое написано: арифметика указателей разрешена внутри массива
When an expression that has integer type is added to or subtracted from a pointer, the
result has the type of the pointer operand. If the pointer operand points to an element of
an array object
, and the array is large enough, the result points to an element offset from
the original element such that the difference of the subscripts of the resulting and original
array elements equals the integer expression. In other words, if the expression P points to
the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and
(P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of
the array object, provided they exist. Moreover, if the expression P points to the last
element of an array object, the expression (P)+1 points one past the last element of the
array object, and if the expression Q points one past the last element of an array object,
the expression (Q)-1 points to the last element of the array object. If both the pointer
operand and the result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined
. If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is evaluated.
Что теперь скажешь?
...
Рейтинг: 0 / 0
virtual methods
    #39652952
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestИли в " И никакого доступа, приводящего к UB " под "доступом" не имелась в виду попытка чтения из объекта?Какой может быть UB при выполнении команд процессора из откомпилированного бинарного файла? Там уже исключения... :)
...
Рейтинг: 0 / 0
virtual methods
    #39652953
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestА при чём тут стандарт C, если обсуждается стандарт C++?А при том, что ANSI C, это LEGACY С++ (читай как "наследство с обременением").

a guestВпрочем, в стандарте C то же самое написано: арифметика указателей разрешена внутри массиваМассивом может быть что угодно. Любой объект можно представить как массив байт, таблицу виртуальных методов можно представить как массив векторов и т.д. и т.п. Для этого даже не обязательно описывать как массив то, что ты хочешь представить как массив.
...
Рейтинг: 0 / 0
virtual methods
    #39652954
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
rdb_deva guestВпрочем, в стандарте C то же самое написано: арифметика указателей разрешена внутри массиваМассивом может быть что угодно. Любой объект можно представить как массивЯ уже понял, что у тебя что угодно может быть чем угодно.
Только мы тут C++ обсуждаем.
...
Рейтинг: 0 / 0
virtual methods
    #39652955
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestМассивом может быть что угодно. Любой объект можно представить как массивЯ уже понял, что у тебя что угодно может быть чем угодно.
Только мы тут C++ обсуждаем.[/quot]Это не у меня, это всегда так было и в C++, и в Си. Именно поэтому на Си до сих пор пишут внутренности операционных систем, прошивки контроллеров и прочую низкоуровневую фигню. :) Ты, случайно, не преподаватель в школе или ВУЗе?
...
Рейтинг: 0 / 0
virtual methods
    #39652957
a guest
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
a guestrdb_deva guestМассивом может быть что угодно. Любой объект можно представить как массивЯ уже понял, что у тебя что угодно может быть чем угодно.
Только мы тут C++ обсуждаем.Это не у меня, это всегда так было и в C++, и в Си. Именно поэтому на Си до сих пор пишут внутренности операционных систем, прошивки контроллеров и прочую низкоуровневую фигню. :) Ты, случайно, не преподаватель в школе или ВУЗе?После того, как тебе предъявили цитату из стандарта C, в который ты просил посмотреть, ты начал нести какую-то чушь.
Я думаю в таком виде продолжать беседу не имеет смысла. От тебя конкретики 0, только переходы на личности и виляния в сторону.
...
Рейтинг: 0 / 0
virtual methods
    #39652958
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestПосле того, как тебе предъявили цитату из стандарта C, в который ты просил посмотреть, ты начал нести какую-то чушь.
Я думаю в таком виде продолжать беседу не имеет смысла. От тебя конкретики 0, только переходы на личности и виляния в сторону.Для начала, прочти, что представляет из себя массив, почему к нему можно обращаться как к указателю, как осуществляется арифметика типизированных указателей и проверь всё это в отладчике. Потом придёшь и будешь спорить. Ok? :)
...
Рейтинг: 0 / 0
virtual methods
    #39652963
rdb_dev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestЗатем, что дальше написано, что otherwise behavior is undefined.
Массива нет — значит при адресной арифметике получается UB.

Вроде вопрос был откуда я взял что там UB и откуда требование про массив. Я ответил. Или опять не ясно?Любой типизированный указатель, формально, уже массив. Такая уж особенность у Си и C++... Другое дело, что в реальности никакого массива там может не быть из-за ошибки программиста, но компилятору об этом, порой, ничего не известно. Попробуй найти потенциальную ошибку в этом простом примере:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
#pragma pack(push, __ALIGN_DWORD)
struct A
{
  int Lo;
  int Hi;

  void* operator new(size_t sz, void* p) {return p;}
};
#pragma pack(pop)

A *a = (A*)malloc(sizeof(A)<<1);
new(&a[0]) A;
new(&a[1]) A;
a[0].Lo = 0x30; a[0].Hi = 0x31;
a[1].Lo = 0x32; a[1].Hi = 0x33;
...
Рейтинг: 0 / 0
virtual methods
    #39652984
Barlone
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a guestBasil A. SidorovЯ повторю, что? насколько мне известно, placement new вообще ничего не делает с переданным ему буфером.А зачем он нужен, если ничего не делает? Можно не вызвать его тогда...
Так это, placement new конструкторы вызывает.
...
Рейтинг: 0 / 0
25 сообщений из 356, страница 8 из 15
Форумы / C++ [игнор отключен] [закрыт для гостей] / virtual methods
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]