Здравствуйте, Programador, Вы писали:
P>Если комитет по недомыслию или для перестраховки написал такое P>
P>delete p;
P>b=p; // UB
P>
P> то тут уж не знаешь смеяться или плакать
Это не для перестраховки. Могут быть платформы, на которых используется сегментная модель памяти. И для операций с адресами удобно использзовать специальные инструкции и регистры, обрабатывающие сегмент и смещение.
При этом процессор, при загрузке указателя, может проверять, например, корректность id сегмента. Если после delete p последняя память в сегменте освободится менеджер может вернуть системе весь сегмент, а система просто разрушит его, сделав селектор сегмента невалидным. При попытке копирования невалидный селектор будет загружен в процесор и начнётся реальное UB...
Затриать же невалидный указатель в памяти всё-таки безопасно...
похожего UB можно добиться даже на x86. Только не с указателями, но с другим типом, валидность которого может проверяться аппаратурой -- с double.
struct UBGenerator { double f1, f2, f3, f4, f5, f6, f7, f8, f9, f10; };
UBGenerator foo()
{
UBGenerator tmp;
return tmp; // UB, может приводить на x86 к реаоьным проблемам :(
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: А разве в OpenSource бывают собеседования? :)
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Programador, Вы писали:
P>>Если комитет по недомыслию или для перестраховки написал такое P>>
P>>delete p;
P>>b=p; // UB
P>>
P>> то тут уж не знаешь смеяться или плакать
E>Это не для перестраховки. Могут быть платформы, на которых используется сегментная модель памяти. И для операций с адресами удобно использзовать специальные инструкции и регистры, обрабатывающие сегмент и смещение. E>При этом процессор, при загрузке указателя, может проверять, например, корректность id сегмента. Если после delete p последняя память в сегменте освободится менеджер может вернуть системе весь сегмент, а система просто разрушит его, сделав селектор сегмента невалидным. При попытке копирования невалидный селектор будет загружен в процесор и начнётся реальное UB... E>Затриать же невалидный указатель в памяти всё-таки безопасно...
Таки да, безопасно (: Assignable requirements сбили с толку.
Здравствуйте, Erop, Вы писали: T>>А можно пример, где оператор "ведёт себя неожиданно" в синтаксическом плане? T>>Мне как-то всё время казалось, что С++ довольно "кудряв" в синтаксисе объявлений, но вот операторы всегда казались довольно простой и логичной в синтаксисе областью эхотага.
E>Вот, ещё придумалось...
всё ли тут хорошо?
Тут как раз "кудрявый" синтаксис обявления скрывает то, что вызывается new[]. Так что это вполне классический пример неявной ошибки удаления массива не массивным delete.
Вроде даже у кого-то из классиков описан.
Здравствуйте, Erop, Вы писали: E>Ты, наверное знаешь, что код delete p; вызовет деструктор *p, а потом позовёт operator delete( p ); E>1) Как вызвать operator delete( void*, size_t );
Если этот опреатор определить в классе, то именно он будет вызываться при удалении экземпляра.
№3.7.3.2 п2
Иначе как и №2 E>2) Как вызвать operator delete( void*, const char* );
Вызывается в случае, вылета исключения из конструктора объекта при конструировании соответствующим по параметрам new.
№5.3.4 пп8,17-20 E>3) Как вызывать operator delete( int );
Неверная сигнатура.
Разумеется, правильные операторы можно вызвать явно как функции.
Здравствуйте, Tonal-, Вы писали:
T>Вроде даже у кого-то из классиков описан.
AFAIK, всё верно, но думал долго
Я это к тому, что и new вроде как оператор, а ясности мало, да и delete запутанно очень определён. И если не знать всё на эту тему досконально, то легко, IMHO, запутаться
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: T>>Вроде даже у кого-то из классиков описан. E>AFAIK, всё верно, но думал долго
Времени не было, вот и "думал долго".
К тому же сказывается то, что я уже ~3 года не работаю с С++...
Здравствуйте, Erop, Вы писали: T>>Вроде даже у кого-то из классиков описан. E>AFAIK, всё верно, но думал долго
Кстати, почему ещё тормозил: Простейший пример для вызова operator delete из конструкции new не отработал с первого раза и заставил усомнится в моём склерозе.
При компиляции мингвой (3.4.5, 4.1.2-dw2, 4.3.0) выводит только
e::new(size_t 1, char* 0x22ff38)
Для того, чтобы отработало как положено надо поместить вызов foo или new в try/catch.
Нельзя сказать,что такое поведение нелогично, но в ступор таки поставило.
Кстати, кто-нибудь может сказать как это согласуется со стандартом? Мне кажется это отступление...
Здравствуйте, Tonal-, Вы писали:
T>Кстати, кто-нибудь может сказать как это согласуется со стандартом? Мне кажется это отступление...
Основное западло состоит в том, что да.
Совсем неловленное исключение стек разматывать не обязано
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском