|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Необходима реализация простейшего менеджера памяти на базе VirtualAlloc. Чтобы не использовать выделение памяти средствами Delphi или FastMM, а обращаться напрямую к операционной системе. Потому что в приложении много багов, которые портят память. Выделение кусков средствами операционной системе должно помочь вызывать Access Violation если что-то пойдет не так. Как я понимаю, выглядит это примерно так: https://www.gunsmoker.ru/2009/01/blog-post.html Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
но примера реализации этих методов на базе VirtualAlloc найти не могу ... ... |
|||
:
Нравится:
Не нравится:
|
|||
23.02.2022, 23:25 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
SafeMM ... |
|||
:
Нравится:
Не нравится:
|
|||
23.02.2022, 23:58 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 Выделение кусков средствами операционной системе должно помочь вызывать Access Violation если что-то пойдет не так. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 00:01 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
_Vasilisk_ Наталья87 Выделение кусков средствами операционной системе должно помочь вызывать Access Violation если что-то пойдет не так. Тут дело скорее в том - чтобы один кусок программы не мог портить память, выделенную другим куском программы. В этом случае VirtualAlloc поможет. Наоборот, есть еще идея - обматывать выделяемые куски памяти "одеялом". То есть выделять вначале пару килобайт, потом запрашиваемый объем памяти, умноженный на 3 (рабочая область посередине), потом еще пару килобайт. Чтобы глючный код мог немного промахиваться и это не приводило к падению приложения. В случае FastMM или других разделяемых менеджеров памяти фактически любой баг в каком-нибудь потоке или таймере может испортить важную память основного потока и приложение упадёт. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 00:10 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Dmitry Arefiev SafeMM Работает под Delphi 7. Но увы, проект с ним вообще не запускается под Delphi XE8. И еще - он какой-то медленный очень. Там много функций для отладки - но тут речь не про отладку а про Release-приложение. Есть в приложении баги или нет - другой вопрос - но нужно минимизировать вероятность падения Release-приложения по причине багов. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 00:16 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 Наоборот, есть еще идея - обматывать выделяемые куски памяти "одеялом". То есть выделять вначале пару килобайт, потом запрашиваемый объем памяти, умноженный на 3 (рабочая область посередине), потом еще пару килобайт. Чтобы глючный код мог немного промахиваться и это не приводило к падению приложения. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 00:20 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
_Vasilisk_ Наталья87 Наоборот, есть еще идея - обматывать выделяемые куски памяти "одеялом". То есть выделять вначале пару килобайт, потом запрашиваемый объем памяти, умноженный на 3 (рабочая область посередине), потом еще пару килобайт. Чтобы глючный код мог немного промахиваться и это не приводило к падению приложения. Исправлять можно у себя на компьютере. Пользователю зачем ошибки видеть? ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 01:01 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Кроме SafeMM ни один менеджер памяти не пережил такой код: Код: pascal 1. 2. 3. 4. 5. 6.
В случае с SafeMM выдало Access Violation, но приложение не упало! Но SafeMM слишком медленный, поэтому и хотелось бы реализации на базе стандартных функций VirtualAlloc. Я думаю, поскольку память VirtualAlloc выделяется системой - подобные ошибки или пройдут незамеченными или вызовут Access Violation, но не будут валить приложение. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 01:59 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 _Vasilisk_ пропущено... А, понял. Цель не исправить ошибки, а завуалировать их Исправлять можно у себя на компьютере. Пользователю зачем ошибки видеть? Отсутствие ошибки порождает у пользователя уверенность что программа работает в штатном режиме. Если выдается адекватное сообщение об ошибке с кнопкой послать отчет разработчику то это нормально. Вообще странный подход конечно, ну да Ваше дело. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 02:11 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Все дело в том, что SafeMM не работает с модулями IdHttp, IdFtp. Экспериментальным путем было проверено, что дело не в моем проекте, а в этих модулях. Есть вот такой код - который нужно переписать с HeapAlloc на VirtualAlloc. Код: 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. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110.
... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 02:51 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Ладно, попробую переделать SafeMM. Идея в том, чтобы выделять большой защищённый блок в 64Кб на каждый запрос по выделению. памяти. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 11:54 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Код менеджера после переделывания. Максимально минимизированный и на базе SafeMM. Большой проект на этом менеджере работает и запускается на Delphi 7. Пустой проект с 1 формой на Delphi XE8 тоже работает. Но стоит подключить 2 модуля USES IdFtp, IdHttp; и проект не запускается - завершаясь с ошибкой Runtime Error 216 at00405353 Иногда выходит access violation at address 00000000 То же самое с исходным SafeMM - стоит подключить модули USES IdFtp, IdHttp; и при запуске приложения с 1 формой выходит ошибка access violation at address 00000000 Как заставить SafeMM работать с родными Delphi-модулями IdHttp, IdFtp или навскидку есть ли очевидные баги в модуле ниже? Код: 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. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100.
Код: 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.02.2022, 16:27 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 есть ли очевидные баги в модуле ниже? Вангую, что нужно сделать заглушки для: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 16:42 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Kazantsev Alexey Наталья87 есть ли очевидные баги в модуле ниже? Вангую, что нужно сделать заглушки для: Код: pascal 1. 2. 3. 4. 5. 6. 7. 8.
Спасибо, помогло. И SafeMM после данного дополнения чудесным образом заработал. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.02.2022, 17:12 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 Экспериментальным путем было проверено, что дело не в моем проекте, а в этих модулях. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.02.2022, 17:39 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
_Vasilisk_ Наталья87 Экспериментальным путем было проверено, что дело не в моем проекте, а в этих модулях. Интересный момент еще. Если использовать данный менеджер памяти (и выделять блоки кратные 4 Кб по каждому чиху - даже если требуется 10 байт) - при примерно 150 Мб занятой оперативной памяти (проверка Диспетчером задач на Win Xp с 4 Гб оперативы) выскакивает ошибка "Out of Memory" - хотя памяти свободной еще вагон. Видимо, есть какие-то ограничения операционной системы на количество выделяемых блоков, в какой-то момент функция VirtualAlloc перестает выделять память. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 00:18 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
_Vasilisk_ Наталья87 Экспериментальным путем было проверено, что дело не в моем проекте, а в этих модулях. Вообще странно, что SafeMM поставляется без этих методов для Delphi XE+, хотя заявлено, что он должен работать на Delphi XE+. Хотя если принять, что это все-таки сторонний менеджер памяти и писали его люди, а устроен он довольно сложно внутри - в нём могут быть и ошибки и недоработки, как в любой программе. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 00:21 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 Видимо, есть какие-то ограничения операционной системы на количество выделяемых блоков, в какой-то момент функция VirtualAlloc перестает выделять память. Это называется фрагментацией адресного пространства. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 00:32 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 при примерно 150 Мб занятой оперативной памяти (проверка Диспетчером задач на Win Xp с 4 Гб оперативы) выскакивает ошибка "Out of Memory" - хотя памяти свободной еще вагон Оперативная память не имеет никакого отношения к выделенной памяти в программе. В оперативной памяти программа может занимать как меньше памяти, чем она выделила (чаще всего), так и больше. Если вы хотите смотреть за потреблением памяти вашей программы, то в диспетчере задач выберите Вид / Выбрать столбцы и поставьте галку на "Объём виртуальной памяти". Также рекомендую: https://www.gunsmoker.ru/2011/04/windows-spin-off.html ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 11:21 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
У VirtualAlloc по умолчанию гранулярность выделения памяти - 64 кб . Это значит, что в 2 Гб адресном пространстве этой функцией можно выделить не более 32'768 блоков. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 11:29 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 Вообще странно, что SafeMM поставляется без этих методов для Delphi XE+, хотя заявлено, что он должен работать на Delphi XE+. Хотя если принять, что это все-таки сторонний менеджер памяти и писали его люди, а устроен он довольно сложно внутри - в нём могут быть и ошибки и недоработки, как в любой программе. SafeMM - это просто экспериментальная демка, proof-of-concept. Уж тем более не предполагается, что его будут использовать в релизе. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 11:32 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
_Vasilisk_ Не поможет. VirtualAlloc выделяет память страницами. Размер страницы - 4096 байт. Т.е. если вы запросили 10 байт, а обратились к 3000, то никто вам ничего не скажет. Не обязательно использовать память с начала страницы. Если цель отловить overflow, то логический блок должен заканчиваться ровно на конце физического, а начинаться где-то в середине этой 4к страницы. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 11:34 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
Наталья87 Но SafeMM слишком медленный, поэтому и хотелось бы реализации на базе стандартных функций VirtualAlloc. VirtualAlloc - это функция ядра Windows. Любой вызов ядра - это очень медленно, поскольку происходит переключение пользовательского режима и режима ядра. И с этим ничего сделать нельзя, никакое переписывание кода здесь не поможет. По сути, SafeMM - это и есть минимальная обёртка к VirtualAlloc, ничего особо больше он не делает. Поэтому общепринятая практика как раз выделять память одним большим куском, а потом логически делить его внутри пользовательского режима, не переключаясь в режим ядра. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 12:00 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
GunSmoker Наталья87 Но SafeMM слишком медленный, поэтому и хотелось бы реализации на базе стандартных функций VirtualAlloc. VirtualAlloc - это функция ядра Windows. Любой вызов ядра - это очень медленно, поскольку происходит переключение пользовательского режима и режима ядра. И с этим ничего сделать нельзя, никакое переписывание кода здесь не поможет. По сути, SafeMM - это и есть минимальная обёртка к VirtualAlloc, ничего особо больше он не делает. Поэтому общепринятая практика как раз выделять память одним большим куском, а потом логически делить его внутри пользовательского режима, не переключаясь в режим ядра. Да, так и получилось в итоге. Через мой менеджер памяти на базе VirtualAlloc работает также медленно (а то и еще медленнее), чем через SafeMM. При этом и памяти жрет больше, чем SafeMM (и приложение по причине OutOfMemory поэтому вылетает даже на 64-разрядных сборках). Т. к. SafeMM хоть и использует агрессивно VirtualAlloc и VirtualProtect, выделяя в разы больше памяти, чем нужно - но все же для мелких блоков он не использует VirtualAlloc. Попробую еще для интереса не по 4 Кб, а сразу по 64 Кб выделять. Хуже судя по всему не будет - просто Диспетчер Задач будет отображать реальный объем потребляемой памяти. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 14:57 |
|
Простейший менеджер памяти на базе VirtualAlloc
|
|||
---|---|---|---|
#18+
GunSmoker _Vasilisk_ Не поможет. VirtualAlloc выделяет память страницами. Размер страницы - 4096 байт. Т.е. если вы запросили 10 байт, а обратились к 3000, то никто вам ничего не скажет. Не обязательно использовать память с начала страницы. Если цель отловить overflow, то логический блок должен заканчиваться ровно на конце физического, а начинаться где-то в середине этой 4к страницы. Для отлова ошибок есть уже готовые SafeMM и FastMM. Но первый слишком медленный и скорее для Debug, а не для Release, хотя с задачей не допустить падения программы и повреждения памяти кривым кодом справляется прекрасно. Второй как-то плохо защищает память от кривого кода . Цель немного другая для Release-сборок. И состоит не только в том, чтобы отловить ошибки. Цель именно в том, чтобы ошибки в программе не приводили к повреждению памяти, последующим глюкам а то и падению приложения (у клиентов на Release-сборке). Как я полагаю - этого можно добиться либо используя агрессивные методы отлова некорректного доступа к памяти вроде SafeMM (но проблема в том, что SafeMM слишком медленный). Либо не отлавливать некорректный доступ к памяти, а просто выделять памяти больше, чем нужно, помещая данные в середину и оборачивая "одеялом". Чтобы как было как танковая броня - ошибки в одном месте программы не приводили к повреждению памяти других участков программы. Чтобы не тормозило и не потребляло горы памяти - очевидно, делать надо это не с помощью VirtualAlloc, а с помощью HeapAlloc. Если просто выделять больше памяти, чем нужно и не ловить ошибки - замедление получается всего на 30% - при этом я полагаю, это должно защищать от порчи памяти. И еще - было принято решение включить Range Check Error и Overflow Check. На Release сборках в том числе. По сути они не так уж сильно замедляют работу программы, как SafeMM, а толку в плане защиты памяти на практике от них немало. Если можно - поясните, пожалуйста, в чем я не права и заблуждаюсь. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.02.2022, 15:07 |
|
|
start [/forum/topic.php?fid=58&msg=40136646&tid=2036594]: |
0ms |
get settings: |
17ms |
get forum list: |
5ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
57ms |
get topic data: |
3ms |
get forum data: |
1ms |
get page messages: |
536ms |
get tp. blocked users: |
0ms |
others: | 313ms |
total: | 934ms |
0 / 0 |