|
Stack Overflow
|
|||
---|---|---|---|
#18+
Почему при Subj программа просто слетает, вместо того чтобы выдать сообщение и работать дальше? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 14:25 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Потому что невозможно работать без свободного места в стэке, это слишком важная часть памяти. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 14:28 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Но исключение предусмотрено и оно генерируется. Если бы было невозможно - поставили бы Halt. Почему не происходит откат по стеку с его освобождением? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 14:35 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Maxim Rusov Почему не происходит откат по стеку с его освобождением? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 14:49 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Как обычно. Если я на N-й глубине вложенности сгенерирую исключение - все корректно откатывается. А если на N+1 возникает Stack Overflow - краш. Почему? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 15:07 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Maxim RusovА если на N+1 возникает Stack Overflow - краш. Какой именно краш? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 15:38 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Молча? Так не бывает. Хоть что-то да должно остаться в Windows Events. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 16:07 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Maxim Rusov Как обычно. Если я на N-й глубине вложенности сгенерирую исключение - все корректно откатывается. А если на N+1 возникает Stack Overflow - краш. Почему? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 16:16 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Ограниченно понял. Оказывается, когда попадаем в корневой Except стек еще не освободился, и мы получаем повторную ошибку при обработке исключения. Стек освобождается при завершении Except блока в DoneExcept (x86) Т.е. ошибку можно обойти как то так: Код: pascal 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.
Но при повторном вызове - все плохо, Stack Overflow уже не возникает, возникает AV и программа все-таки слетает. Странно все это... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 16:23 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Нашел такое: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/resetstkoflw?view=msvc-160 Интересно, это может помочь? И как это можно из Delphi вызвать?... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 16:46 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Тут надо понять принцип возбуждения Stack Overflow. У стека потока в конце ставится специальная страница, которая имеет атрибут доступа GUARD. Когда поток исчерпает свободное место в стеке - он попытается записать в эту страницу. В результате страница будет выделена обычным образом, а атрибут GUARD будет перенесён на следующую страницу. Но если эта страница была последней - то атрибут GUARD переносить некуда, ибо там будет зарезервированное место с NO_ACCESS. И когда такое случается - возбуждается исключение Stack Overflow. При этом картина следующая: стек выделен полностью и ограничен с двух сторон страницами с NO_ACCESS. Страницы с GUARD нет. А управление передаётся на обработчик Stack Overflow, который начинает работать в только что выделенной странице. Предполагается, что приложение продолжит выполнение и обработает Stack Overflow. В типичных приложениях Delphi это приведёт к ShowMessage('Stack Overflow'). Однако, если для обработки исключения приложению потребуется больше памяти на стеке, чем там осталось (одна страница, 4 кб) - то в итоге оно попробует записать в область памяти с NO_ACCESS. В ответ на это система в конечном итоге закроет приложение извне. Упражнение: что не так с Delphi-вым GetModuleName с его статичным буфером в 520 байт для имени? Аналогичное справедливо, если исключение Stack Overflow было обработано, но приложение продолжило выполняться дальше и снова попало в ситуацию, когда должно было бы возбуждаться второе Stack Overflow. Но поскольку GUARD-страницы больше нет, то и возбуждать нечего. В итоге приложение снова упадёт с фатальным Access Violation при попытке записи в NO_ACCESS. Аналог _resetstkoflw на Delphi выглядит примерно так: Код: pascal 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. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88.
Она может помочь во втором случае, но не может помочь в первом, потому что она, по сути, просто восстанавливает GUARD-страницу, но только при условии, что для этого есть место . Дело в том, что _resetstkoflw можно использовать только следующим образом: Код: pascal 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 18:36 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
GunSmoker, Да, спасибо. Уже сам спортировал _resetstkoflw, а нужно было просто подождать :) Такой код теперь работает стабильно: Код: pascal 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.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 18:49 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
А почему при старте приложения не вызывать SetThreadStackGuarantee со значением, например, 16K? MSDN прямо в первом предложении к описанию функции как бы намекает, что при Stack Overflow столько будет доступно как раз на вызов исключения. Или нет? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 18:57 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
O_O_P, Но ResetStkOflw все равно делать нужно, там дальше написано ... |
|||
:
Нравится:
Не нравится:
|
|||
06.09.2021, 19:08 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Кстати, до кучи GunSmoker Дело в том, что _resetstkoflw можно использовать только следующим образом: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Отквоченное относится только к x86. В x64 стек освобождается и _resetstkoflw в except вызывать можно. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.09.2021, 14:07 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Да, к счастью в x64 - табличные исключения, указатели на обработчики исключкений хранятся в отдельной секции файла, не в стеке, поэтому там нет никаких проблем размотать стек сразу. Но в x86 указатели на обработчики исключений находятся в стеке, поэтому стек отмотать нельзя, пока обработка исключения не будет завершена. В противном случае (если стек размотать сразу) обработчик исключения начнёт выполняться и затрёт указатели на следующие обработчики. ... |
|||
:
Нравится:
Не нравится:
|
|||
07.09.2021, 16:31 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
А вроде бы везде пишется, что и там и там Delphi применяет SEH, а не какой-нибудь SJLJ. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
07.09.2021, 17:48 |
|
Stack Overflow
|
|||
---|---|---|---|
#18+
Dimitry Sibiryakov, он и есть, просто для 32-битного режима стандарта нет и все делают как хотят борланд исторически стек использовал для хранения цепочек try в 64-битном формате мелкософт эту "недоработку" устранил, впрочем, как уже заведено "через одно место" ... |
|||
:
Нравится:
Не нравится:
|
|||
07.09.2021, 18:13 |
|
|
start [/forum/topic.php?fid=58&msg=40095488&tid=2037041]: |
0ms |
get settings: |
11ms |
get forum list: |
10ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
68ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
59ms |
get tp. blocked users: |
1ms |
others: | 274ms |
total: | 446ms |
0 / 0 |