Re[27]: Книжка по UB
От: rg45 СССР  
Дата: 14.08.25 10:45
Оценка:
Здравствуйте, so5team, Вы писали:

S>PS. Для разнообразия чуть измените конструктор s1:

S>
S>struct s1 {
S>  virtual void f() { std::cout << "s1::f" << std::endl; }

S>  s1() {
S>    call_f();
S>  }

S>  void call_f();
S>};

S>// Где-то совсем в другом месте, возможно даже в другой единице трансляции.
S>void s1::call_f() {
  this->>f(); // (3)
S>}
S>

S>У нас теперь нет точки (1) в которой компилятор что-то точно знает.
S>Зато есть точка (3), которая на разных путях к call_f приводит к разному наблюдаемому поведению.

Ну, ладно, сдаюсь

Хотя, может же и проинлайнить
--
Справедливость выше закона. А человечность выше справедливости.
Re[28]: Книжка по UB
От: so5team https://stiffstream.com
Дата: 14.08.25 11:06
Оценка:
Здравствуйте, rg45, Вы писали:

R>Хотя, может же и проинлайнить


С точки зрения описанной в проблемной главе книги ситуации это вообще никакой роли не играет.

А ситуация такая, что в "более лучших"(tm) языках мы можем полагаться на вызов "самой свежей" реализации виртуального метода в конструкторах/деструкторах. И на этом могут быть построенны некоторые проектные решения. Типа того, что есть базовый класс, в конструкторе которого всегда вызывается виртуальный метод preallocate_resources. А производным классам достаточно просто переопределить этот метод у себя не заботясь о том, кто его вызовет (вызовет как раз базовый класс).

Тогда как в С++ этот паттерн не будет работать от слова совсем. С preallocate_resources нужно будет колупаться в конструкторах классов-наследников.

Каким образом при этом в C++ будет происходить вызов preallocate_resources ну вот не важно со слова совсем, если вы обычный пользователь языка.

Если вы плохо знаете C++ или тащите в С++ привычки из "более лучших"(tm) языков, то ждите сюрпризов.

О чем, собственно, в этой проблемной главе и написано.
Re: Книжка по UB
От: student__  
Дата: 14.08.25 11:39
Оценка: -1
Здравствуйте, LaptevVV, Вы писали:

LVV>Рекомендую!


В книге ошибочный посыл прямо во введении:

>Все начинается просто и незатейливо: обычный десятиклассник увлекается программированием, знакомится с алгоритмическими задачками, решения которых должны быть быстрыми. Узнает о языке C++


"алгоритмы должны быть быстрыми" — это неоднозначное выражение. Реализация может быть быстрая. И "быстрота алгоритмов" даже у школьника должна ассоциироваться с ассимптотической сложностью.
"узнаёт о C++" здесь натянуто, как сова на глобус.
Более корректно, как уже тут написали, когда уже опытнйый сишник видит плюсы, и думает, что там всё по уму сделано, а на самом деле...
Re[29]: Книжка по UB
От: rg45 СССР  
Дата: 14.08.25 12:10
Оценка:
Здравствуйте, so5team, Вы писали:

R>>Хотя, может же и проинлайнить


S>С точки зрения описанной в проблемной главе книги ситуации это вообще никакой роли не играет.


Ну, я согласился уже. Есть общие требования к виртуальным функциям, и есть уточнения к этим требования для конструкторов/деструкторов. И эти уточнения не отменяют общие требования, а только уточняют их. А те случаи, когда компилятор может заменить виртуальный вызов на прямой — это следует трактовать как оптимизации, не меняющие поведение. Всё верно?

S>А ситуация такая, что в "более лучших"(tm) языках мы можем полагаться на вызов "самой свежей" реализации виртуального метода в конструкторах/деструкторах.


Да, я в курсе. У них же там нет и детерминированного времени жизни объектов, поэтому могут позволить себе такой беспредел.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 14.08.2025 12:22 rg45 . Предыдущая версия . Еще …
Отредактировано 14.08.2025 12:12 rg45 . Предыдущая версия .
Re[23]: Книжка по UB
От: rg45 СССР  
Дата: 14.08.25 12:15
Оценка:
Здравствуйте, Pzz, Вы писали:

R>>Причем, неотличимы с точки зрения требований стандарта. Отсюда следует, что у нас нет никаких оснований, чтобы утверждать или отрицать "виртуальную диспетчеризацию" в конструкторах и деструкторах. О которой, кстати сказать, в стандарте вообще нет никаких упоминаний. Это термин, расчитанный на интуитивное восприятие. Тут было бы неплохо определиться для начала, о чём мы вообще спорим.


Pzz>По-моему, вы спорите о терминах


Скорее о трактовках и интерпретациях.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: Книжка по UB
От: B0FEE664  
Дата: 15.08.25 18:05
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Матерную поэму. В этой поэме должно быть много красивых, выразительных и поэтичных русских матерных слов.


складывать строку с числом — так себе идея.
Со знаковым char есть более простая и вместе с тем коварная проблема. Языка С она тоже касается:

char convert(char ch)
{
    char table[256] = { некоторые значения для перестановки };
    return table[ch];
}


И всё работает до перехода на компилятор, где char (какого-то лешего) знаковый.
И каждый день — без права на ошибку...
Re[3]: Книжка по UB
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 15.08.25 18:18
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>И всё работает до перехода на компилятор, где char (какого-то лешего) знаковый.


char по-моему везде по умолчанию знаковый. Но лично я уже давно привык явно кастовать, в данном случае я кастовал бы так: (size_t)(unsigned char)ch
Маньяк Робокряк колесит по городу
Re[11]: Книжка по UB
От: Лазар Бешкенадзе СССР  
Дата: 19.08.25 07:16
Оценка: -1 :)
Здравствуйте, Pzz, Вы писали:

ЛБ>>

При деструктурировании наоборот — часть объекта-наследника уже уничтожена, и если позволить динамический вызов, можно легко получить use-after-free.


ЛБ>>Человек явно не понимает механизма и считает что при динамическом вызове может быть вызвано что-то из производного класса который уже разобран.


Pzz>Человек явно пишет, что ничего из полуразобранного производного класса вызвано быть не может и объясняет почему.


Pzz>Я удивлён, что ты понимаешь этот текст строго наоборот написанному.


Я боюсь что-то не так прочитал именно ты. Показываю еще раз:

если позволить динамический вызов, можно легко получить use-after-free


Динамический вызов никто не запрещает и вроде где-то тут ты сам писал об этом.

А вот автор не понимает сути и его "решение" явно заменить виртуальный вызов на статический хотя в некоторых сценариях это может привести к изменению поведения корректно работающей программы.

Вот еще один pearl:

Радуйтесь! Это одно из немногих мест в C++, где вас защитили от неопределенного поведения со временами жизни!


Это не защита и к временам жизни этот UB не имеет никакого отношения. UB в этом коде называется "a virtual call to a pure virtual function" а компилятор своей оптимизацией просто замел мусор под коврик.

-
Re[4]: Книжка по UB
От: B0FEE664  
Дата: 22.08.25 15:44
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Мне еще вот такое очень понравилось:

  Скрытый текст
Pzz>
Pzz>// пример взят из блога https://mohitmv.github.io/blog/Shocking-Undefined-Behaviour-In-Action/
Pzz>int main() {
Pzz>  char buf[50] = "y";
Pzz>  for (int j = 0; j < 9; ++j) {
Pzz>    std::cout << (j * 0x20000001) << std::endl;
Pzz>    if (buf[0] == 'x') break;
Pzz>  }
Pzz>}
Pzz>

Pzz>Тут компилятор решает вынести умножение из тела цикла. Заменяет ++j на j += 0x20000001, ну и верхнюю границу, девятку, тоже умножает на 0x20000001. А что, имеет право, целочисленное переполнение для знаковых типов — это UB. В итоге цикл на 9 оборотов становится бесконечным.

Не, мне не нравится. j не должен принимать отрицательные значения, значит он должен быть unsigned. К тому же я не вижу смысла в этом коде.
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.