170 похожих чатов

@Endill Если позволите, я хотел бы начать новый "раунд". 1. В

соответствии с http://eel.is/c++draft/basic.types#basic.compound-3.1 имеется четыре категории значений указателей. С последними двумя всё более-менее понятно (ptr == nullptr или указатель на область внутри освобождённого storage). Но вот допустим, что выражение
reinterpret_cast<T *>(reinterpret_cast<char *>(ptr) + 1)
было бы well-formed, и при этом sizeof(T) > 1 (то есть адрес не на начало объекта), или вообще взять наобум число и сделать из него указатель. Как тогда отнести такие значения к категориям? Указатель на объект, которого не существует? (http://eel.is/c++draft/basic.types#footnote-46) Значит, категория значения выбирается в соответствии с контекстом (существует ли действительно объект по такому адресу такого типа, и указывает ли указатель на него/на область за его концом), ведь иначе не было бы категории pointer past the end (такие указатели были бы pointer to an object without lifetime). Но если категория выбирается из контекста существования объекта по адресу, как можно считывать объект в виде байт (http://eel.is/c++draft/basic.lval#11)? Просто получается, что мы пытаемся считать объекты типа unsigned char (или двух других), к примеру при помощи
reinterpret_cast<unsigned char *>(&t)
, но на самом деле, в контексте, никаких unsigned char объектов не существует на данный момент, и в соответствии с http://eel.is/c++draft/basic.memobj#basic.life-6 всё очень плохо. Единственное объеснение что я нахожу, так это то, что http://eel.is/c++draft/basic.types.general#def:representation,object существует одновременно с любым объектом, которому оно соответствует, и когда мы считываем объект как unsigned char, на самом деле мы читаем его object representation. Значит можно легально взять адрес объекта, преобразовать его к unsigned char и совершить indirection к любому байту с целью read значение.
2. Перейдём к пункту http://eel.is/c++draft/basic.memobj#basic.life-6. Относительно значений, "any pointer that represents the address of the storage location where the object will be or was located", здесь подразумеваются указатели на первый байт объекта или возможно куда-то в середину объекта также? То есть имеются ли здесь ввиду указатели на байты storage, которое занимал объект, или же именно указатели, которые "point to" (http://eel.is/c++draft/basic.types#def:point). Зачем имеется возможность преобразовать эти указатели в cv-q void * и затем в cv-q unsigned char* ? Что касается сущности, какие именно это указатели: только деклараторы или expressions тоже, а что если два валидных выражения разного типа указывают на один и тот же байт памяти? Хотя, так как выражения лишь промежуточный шаг между декларатором и значением, и судя по http://eel.is/c++draft/gram.expr#:this и http://eel.is/c++draft/basic.memobj#basic.life-example-1, выражения тоже... Тогда что имеется в виду под glvalue в следующем пункте? (http://eel.is/c++draft/basic.memobj#basic.life-7) Выражения, но лишь те, что не являются указателями? Затем, допустим, в в хранилище объекта был создан новый, тогда выражения, на основе связанных со старым объектом никаким образом не могут быть использованы для доступа к новому объекту (включая, когда новый объект начинается не по тому же адресу)? И на последок. Имя массива преобразуется к указателю на первый элемент массива по определению (http://eel.is/c++draft/conv.array), а операция subscripting (http://eel.is/c++draft/expr.sub, http://eel.is/c++draft/dcl.array#example-4) также использует это преобразование. И что в этом случае? Эти определения лишь говорят, на что при использовании таких выражений в обычном случае мы обратимся к объекту, который является элементом массива? UB из-за обращения к умершим элементам массива? Или же, так как массив не умирает, то и не умирает его object representation, и subscription через имя массива приводит к считыванию его object representation?
А вообще, я бы не отказался почитать статьи, если у вас какие есть на примете.

1 ответов

15 просмотров

1. 1) в том же пункте под списком категорий значение указателя описывается как, выражаясь кратко, соответствующее первому байту объекта. о поведении программ с другими значениями указателей стандарт ничего не говорит — undefined behavior во всей красе. 2) unsigned char объекты на месте «большого» объекта вполне себе существуют согласно basic.types.general#4 3) я считаю, что поведение такого кода описано в expr.reinterpret.cast#7, expr.static.cast#13, expr.add#4.2, expr.unary.op#1, basic.lval#11 и basic.types.general#4 2. 1) напомню, что этот пункт не релевантен для того вашего примера, где буфер предоставляет storage для другого объекта 2) адрес объекта это адрес первого байта, если коротко. подробности в intro.object-9 3) что касается преобразования в void и дальше, это, наверное, нужно для переиспользования storage посредством имеющегося указателя на объект, который там был, в том числе частями 4) указатели это полноценные объекты — они и имеются в виду в basic.life#6. ваши рассуждения про деклараторы мне совсем не понятны 5) в basic.life#7 речь о glvalue, которые можно «получить», например, разыменовав указатель из пункта 6 6) «переиспользовать» выражения можно только если удовлетворены критерии transparently replaceable, чему посвящен пункт 8 7) array-to-pointer преобразование (decay) происходит не по определению, а лишь там, где оно разрешено или не запрещено. например, оно не применяется к аргументам sizeof. но это так, к слову ход мысли дальше не улавливаю, но то, что там написано, кажется, пересекается со сказанным мной выше и пожалуйста, выделяйте в таких простынях пункты, чтобы было легче обозначать, на что я отвечаю

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

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Гайс, вопрос для разносторонее развитых: читаю стрим с юарта, нада выделять с него фреймы с определенной структурой, если ли чо готовое, или долбаться с ринг буффером? нада у...
Vitaly
9
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
длина пакета фиксированная, или меняется?
Okhsunrog
7
Карта сайта