Этот баннер — требование Роскомнадзора для исполнения 152 ФЗ.
«На сайте осуществляется обработка файлов cookie, необходимых для работы сайта, а также для анализа использования сайта и улучшения предоставляемых сервисов с использованием метрической программы Яндекс.Метрика. Продолжая использовать сайт, вы даёте согласие с использованием данных технологий».
Политика конфиденциальности
|
|
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Доброго времени суток. 1. В коде приведённого ниже метода main, переменной b я присваиваю новое значение после её инициализации. Поскольку переменная - это именованный участок памяти, то присвоение b (ссылке на этот участок) нового значения - это запись новых данных в этот именованный участок, т.е. перезапись существующего контента. Согласно логу вывода (см. ниже) я вижу, что сразу после задания нового значения, происходит вызов его деструктора, хотя ещё не достигнута граница области видимости этой переменной. Я так понимаю, что компилятор C++ пытается вызвать деструктор ранее хранившегося по указанной ссылке объекта, однако делает это уже после того, как объект был перезаписан. В результате вызывается деструктор нового объекта и получается, что он создаётся и тут же уничтожается. Я правильно понимаю поведение? 2. В ходе выполнения программы, она аварийно завершается. Почему не срабатывают catch? Исходный код Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. Результат A::A(const string& name): Anton constructor. A::~A(): Anton destructor. A::A(const string& name): Boris constructor. B::B(const string& name): Boris constructor. &b = 00000000002CF630 A::A(const string& name): Boris2 constructor. B::B(const string& name): Boris2 constructor. B::~B(): Boris2 destructor. A::~A(): Boris2 destructor. &b = 00000000002CF630 A::A(const string& name): Ciprus constructor. B::B(const string& name): Ciprus constructor. C::C(const string& name): Ciprus constructor. C::~C(): Ciprus destructor. B::~B(): Ciprus destructor. A::~A(): Ciprus destructor. B::~B(): destructor. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 13:25 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Compositumя вижу, что сразу после задания нового значения, происходит вызов его деструктора, хотя ещё не достигнута граница области видимости этой переменной. Достигнута. Это деструктор временной переменной B::B, которая уничтожается сразу после копирования её в b. В твоём коде ошибка - не определён конструктор копирования для B, что приводит к затиранию указателя на А без его освобождения. Posted via ActualForum NNTP Server 1.5 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 13:57 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Убрал неотносящийся к вопросу мусор (можно в следующий раз не загромождать код ?) Код: plaintext 1. 2. 3. 4. 5. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 13:59 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Compositum, откройте для себя временные объекты и конструктор копирования ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 14:02 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
А, здесь ошибка у меня. В третей строке должно быть: Код: plaintext 1. (Как Дмитрий выше написал) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 14:04 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Dimitry Sibiryakov- не определён конструктор копирования для B Точнее копирующий оператор присваивания ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 14:27 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
_<>_Dimitry Sibiryakov- не определён конструктор копирования для B Точнее копирующий оператор присваивания Есть копирующий конструктор ( copy constructor ) и оператор присваивания (assignment operator) и в Cx11 есть ещё конструктор перемещения. А понятия "копирующий оператор присваивания" не существует. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 15:10 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
CompositumСогласно логу вывода (см. ниже) я вижу, что сразу после задания нового значения, происходит вызов его деструктора, хотя ещё не достигнута граница области видимости этой переменной. Я так понимаю, что компилятор C++ пытается вызвать деструктор ранее хранившегося по указанной ссылке объекта, однако делает это уже после того, как объект был перезаписан. В результате вызывается деструктор нового объекта и получается, что он создаётся и тут же уничтожается. Я правильно понимаю поведение? Неправильно. Удаляется временный объект, созданный тут: Код: plaintext 1. Справа от присваивания стоит временный объект класса B::B, он создаётся, присваивается в b, а затем он должен уничтожится, что и происходит. Ты бы это сам понял, если бы печатал в своих трейсах ещё и идентификатор объекта, который создаётся или уничтожается (идентификатор объекта -- это в С++ его адрес). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 15:17 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
до конструкторов копирования и копирующего присваивания я ещё не дочитал: я дочитываю 17-ю главу, а они в 18-й. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 15:25 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Compositum, несколько замечаний. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Лучше Код: plaintext 1. Если данный объект доступен, то его член n также всегда доступен, что позволяет возвращать его значение по константной ссылке, а не по значению. Это позволяет съэкономить на копировании объекта. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Рассмотрим Код: plaintext 1. a - указатель на A. Он может быть невалидным. Если он невалидный, то его разименовывать нельзя, и в теле надо проверять, что он невалидный и (видимо) выкидывать исключение. Код: plaintext 1. Но если a валиден, то он всегда содержит n и может его вернуть по ссылке, т.о. это мы можем сделать и тут: Код: plaintext 1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 15:26 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
MasterZivЕсли данный объект доступен, то его член n также всегда доступен, что позволяет возвращать его значение по константной ссылке, а не по значению. Это позволяет съэкономить на копировании объекта. Да, спасибо, это я упустил. MasterZiva - указатель на A. Он может быть невалидным. Если он невалидный, то его разименовывать нельзя, и в теле надо проверять, что он невалидный и (видимо) выкидывать исключение. Да, я в курсе, но не делал проверки в этом примере, дабы сократить код. В реальном коде я, конечно же, буду выполнять проверку всех входящих параметров и проверку результата, прежде чем его возвращать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 15:32 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Compositum, catch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартнеый. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 21:39 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
MasterZivCompositum, catch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартнеый.То есть "по стандарту" бывают исключения а бывают "просто умерли"? Какие интересные стандарты. Я всегда считал что исключения изначально были придуманы именно для того чтобы программы не падали. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 22:16 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
MasterZivcatch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартный. Честно говоря, я ожидал, что catch(...) должен был гарантированно отлавливать любую ситуацию, прошедшую мимо catch(exception& e). Как обычно отлавливают и обрабатывают подобные "падения"? У Стровструпа я перенял обозначенную выше конструкцию, но там не говорилось о том, что что-то может пролететь мимо кассы... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 22:20 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
CompositumMasterZivcatch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартный. Честно говоря, я ожидал, что catch(...) должен был гарантированно отлавливать любую ситуацию, прошедшую мимо catch(exception& e). Как обычно отлавливают и обрабатывают подобные "падения"? У Стровструпа я перенял обозначенную выше конструкцию, но там не говорилось о том, что что-то может пролететь мимо кассы...В идеале так и должно быть. В реальности все эти try{}catch отлавливают только то что было кем-то throw. Либо в самой программе, либо в одной из библиотечных функций. Не уверен было ли это сделано специально или получилось "как обычно". Но для ловли реальных исключений в виндах есть отдельный механизм: Structured Exception Handling. Читай здесь: http://msdn.microsoft.com/en-us/library/ms680657(VS.85).aspx ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 22:27 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
White OwlНо для ловли реальных исключений в виндах есть отдельный механизм: Structured Exception Handling. А какого-нибудь системно-независимого варианта нет? Чтобы не лепить директивы препроцессора для Windows\Linux... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 22:29 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
CompositumWhite OwlНо для ловли реальных исключений в виндах есть отдельный механизм: Structured Exception Handling. А какого-нибудь системно-независимого варианта нет? Чтобы не лепить директивы препроцессора для Windows\Linux...Нет, нету. Но их собственно говоря всего два: В виндах есть SEH, в остальном мире signal(SIGSEGV). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.06.2013, 22:38 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
White OwlТо есть "по стандарту" бывают исключения а бывают "просто умерли"? Нет. По стандарту бывают исключения, как часть языка С++, бывают сигналы, как часть С, и бывают undefined behavior. Все четко и понятно расписано в каком случае что ожидать, или не ожидать (для UB). Например, деление на 0 в рантайме - это UB. Результатом может быть все что угодно. И естественно нет стандартного способа обрабатывать то, что в стандарте объявлено как UB. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 01:53 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyWhite OwlТо есть "по стандарту" бывают исключения а бывают "просто умерли"? Нет. По стандарту бывают исключения, как часть языка С++, бывают сигналы, как часть С, и бывают undefined behavior. Все четко и понятно расписано в каком случае что ожидать, или не ожидать (для UB). Например, деление на 0 в рантайме - это UB. Результатом может быть все что угодно. И естественно нет стандартного способа обрабатывать то, что в стандарте объявлено как UB.И что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 02:06 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
White OwlИ что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще. Вы неверно понимаете суть UB. В С/С++ UB объявляется то, что невозможно эффективно реализовать на большинстве поддерживаемых платформ. Поэтому обработку любого из случаев UB невозможно сделать частью языка/станд. библиотеки, иначе бы надобности в самих UB не было. То, что на некоторых платформах такая обработка возможна, ничего не меняет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 02:15 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
Anatoly MoskovskyWhite OwlИ что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще. Вы неверно понимаете суть UB.Правда? Ну объясните, в чем же эта сакральная суть? "Случилось деление на ноль, программа умерла - значит так хотели высшие силы, смиримся братья." Так что-ли? Anatoly MoskovskyПоэтому обработку любого из случаев UB невозможно сделать частью языка/станд. библиотеки, иначе бы надобности в самих UB не было. То, что на некоторых платформах такая обработка возможна, ничего не меняет.В UB надобности вообще никогда нет, на то они и U! К тому-же, реализацию всех этих исключений которые сейчас отлавливаются только ОС и приводят к смерти приложения можно с легкостью сделать на сигналах (везде кроме виндов) и оформить это как отдельную библиотеку - расширение для stl. Ну не будет эта библиотека на винде работать - не она первая, не она последняя. И вообще, когда я изобретаю язык - мне до лампочки насколько эффективно какая-то желаемая фича реализуется на большинстве поддерживаемых платформ. Поддерживается хоть как-то, хоть где-то и слава богу. Не поддерживается вообще нигде - не беда, сделаем через эмуляцию. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 06:05 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
White OwlИ что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще.Ну например то, что в какой-то системе в этом случае программа сразу убивается без шансов что либо сделать (как TerminateProcess или kill -9 в unix). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 08:33 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
White OwlНу объясните, в чем же эта сакральная суть? В UB надобности вообще никогда нет UB нужны для того чтобы дать компилятору возможность более эффективно реализовать остальной язык, те части, где нет UB. Эффективность - это вообще основная причина, по которой С и С++ до сих пор живы. White OwlИ вообще, когда я изобретаю язык К счастью С и С++ изобретены и развиваются не вами :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 11:18 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
CompositumMasterZivcatch не срабатывает, потому что у тебя не исключение происходит, а просто падает программа. Это не должно транслироваться в исключение, в MS C такой режим есть, но он не стандартный. Честно говоря, я ожидал, что catch(...) должен был гарантированно отлавливать любую ситуацию, прошедшую мимо catch(exception& e). Как обычно отлавливают и обрабатывают подобные "падения"? У Стровструпа я перенял обозначенную выше конструкцию, но там не говорилось о том, что что-то может пролететь мимо кассы... Значит ты ошибался. Ведь у Страустрапа и обратное наверняка нигде не декларировалось. В MSVC шном компиляторе есть поддержка SEH и интеграция его с обычными с++ исключениями, но не полная (часть функций SEH недоступна через exceptions). Общего универсального механизма нет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 12:16 |
|
||
|
деструктор... catch...
|
|||
|---|---|---|---|
|
#18+
White OwlAnatoly Moskovskyпропущено... Нет. По стандарту бывают исключения, как часть языка С++, бывают сигналы, как часть С, и бывают undefined behavior. Все четко и понятно расписано в каком случае что ожидать, или не ожидать (для UB). Например, деление на 0 в рантайме - это UB. Результатом может быть все что угодно. И естественно нет стандартного способа обрабатывать то, что в стандарте объявлено как UB.И что мешает объявить все эти UB как какой-нибудь system_exception и отлавливать его в обычном catch()? И тогда не будет никаких UB вообще. Вообще говоря, другой характер исключений на системном уровне. Программные exceptions программа призвана ловить и возможно обрабатывать, это прикладной уровень. Системные ошибки типа нарушения защиты памяти особо в приложении не обработаешь. Там конечно не всегда так все просто, как я написал, но в общем идея такова. Плюс ещё и кардинальная разница в идеологии системных ошибок в винде и юнихах. Кстати если вспомнить какие-нибудь Dec (см эвм) или IBM (ес эвм), там ни исключений, ни сигналов вообще не было, если я не ошибаюсь. Если что — сразу с копыт и в мусорку, никаких разговоров. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.06.2013, 12:28 |
|
||
|
|

start [/forum/topic.php?fid=57&msg=38308340&tid=2020126]: |
0ms |
get settings: |
11ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
168ms |
get topic data: |
13ms |
get forum data: |
3ms |
get page messages: |
64ms |
get tp. blocked users: |
2ms |
| others: | 286ms |
| total: | 570ms |

| 0 / 0 |
