| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Для новичков > Утечка памяти на стыке приложение - WebBrowser |
| Автор: kami 11.11.2012, 20:37 | ||
| Здравствуйте, дамы и господа! Имею приложение, содержащее только TWebBrowser. В него загружается локальная страничка (подгружающая карту из интернета), после чего - начинают выполняться JavaScript, динамически генерируемые программой (машинка передвигается по карте). Память начинает кушаться (смотрю ProcessExplorer-ом, Private bytes). Причем, это заметно даже на одном объекте. А их предполагается около полутора тысяч. По моим подсчетам, чуть меньше, чем через сутки приложение свалится с Out of memory. А оно должно работать 24х7. На этом тестовом примере за 8 часов работы размер программы (VirtualSize) возрастает до 1 Гб. FastMM молчит. если убрать всего одну строчку, а именно - передачу скрипта в TWebBrowser, то потребление памяти не увеличивается:
Если использовать этот же код (в смысле - тот, который передается в работающий TwebBrowser) непосредственно на странице, открытой в IE, то память так же не возрастает. Просмотрел в интернете, что пишется по этому поводу, нашел только одно: рекомендуют не пользоваться свойством TWebBrowser.Document. Перешел на использование TWebBrowser.ControlInterface - не помогло. Пытался использовать TEmbeddedWB - проблема та же. Помогите решить... Примечание: во вложении тестовое приложение и файлы: 2GISMap.html предназначен для работы в составе приложения, "2GISMap - самостоятельная работа.html " - для отображения непосредственно в браузере. |
| Автор: MetalFan 12.11.2012, 07:11 | ||
| Ну так правильно, скрипт то какой? видимо в нем ресурсы какие-то выделяются браузером. В жаваскрипте ж нет необходимости очищать память за собой, все по идее сделает уборщик... отсюда и возможны утечки. Это вопрос скорее в раздел по жаваскрипту. Предлагаю var myMarker объявить в html файле, а в скрипте в pas файле убрать var, т.е. просто работать с этой переменной. для начала. далее наверное в раздел веб-программирования таки. имхо. кстати, и еще, если планируется работа в оффлайне, то в html файле неплохо бы перелинковать
на локальный файл. |
| Автор: Illusion Dolphin 12.11.2012, 09:08 | ||||||
Это не тру для Javascript, тем более для IE.
А что с Private Bytes? А что за скрипт выполняется? Я ркомендую статью на learn.javascript.ru по утечкам памяти в JavaSctipt http://learn.javascript.ru/optimize - там много идей можно подсмотреть, где могут быть утечки.
Хихи |
| Автор: kami 12.11.2012, 09:18 | ||||
Не помню уже, но с примерно 24 мегабайт выросло до... чтоб не соврать, где-то на порядок, т.е. где-то до 200 В тестовом примере - только один, выполняющийся по таймеру (однократно выполняемый скрипт при загрузке странички рассматривать не будем). Выглядит так:
Читал, увы - не помогло... |
| Автор: kami 12.11.2012, 10:16 | ||||
Поборол с помощью гугла.
|
| Автор: MetalFan 12.11.2012, 22:35 |
почему? |
| Автор: MetalFan 12.11.2012, 23:01 | ||
| kami, кстати, поменял твой код немного. Похоже, что проблемы то с "утечкой" при выполнении то и нет...
Если дергаем ее "на месте", то память практически не "утекает". Похоже, что просто динамическая подгрузка карты кушает почуть память... |
| Автор: Illusion Dolphin 13.11.2012, 00:10 | ||
Для элементов с id некотоные ие автоматически создают переменные (с именем как id) и если не писать var то можно натолкнуться на странные ошибки. |
| Автор: MetalFan 13.11.2012, 07:03 |
| Illusion Dolphin, так я предлагал перенести объявление переменной (var) в тело скрипта на самой странице... а не вообще отказаться от var. |
| Автор: kami 13.11.2012, 07:34 | ||
Может, и нет. Но более реальный код, чем в моем вопросе (300 объектов, на нем как раз-таки и была обнаружена проблема роста памяти), работающий через EmbeddedWB.ExecScriptEx (вместо ExecScript) за те же 8 часов дал прирост PrivateBytes с 33 до 34 Мб. В то время, как работа ExecScript... ну, об этом я писал уже Еще раз - огромное спасибо за вариант решения проблемы, над которой я бился 3 дня.. Добавлено @ 07:36
Карта, вообще-то должна была загрузиться 1 раз и всё. Подгрузка данных должна была производиться только при передвижении карты мышкой или изменении ее масштаба. Upd: кстати, возможно сыграла свою роль и небольшая правка исходников как WB, так и EWB - замена property Document с index ххх на Get_Document. Но - это было нагуглено первым делом до постановки вопроса. |
| Автор: MetalFan 13.11.2012, 13:24 | ||
а можно по-подробнее, так сказать, для анналов истории) |
| Автор: kami 13.11.2012, 16:30 | ||||||
MetalFan, конечно. Собственно, это не является секретом, Яндекс по запросу "WebBrowser утечка памяти" сразу выдает кучу тем, где это обсуждается.
Подводя итог (все-таки, форум для начинающих): для TEmbeddedWB - открываем файл SHDocVw_EWB, ищем в классе TEWB строчку
и меняем ее на
После этого - перебилд пакета, в котором TEmbeddedWB сидит. Аналогично меняется для TWebBrowser, но думаю, что в этом случае нужно будет перезакинуть новую dcu-шку в папку Lib. Не мой, правда, случай - у меня навигация по страницам не ведется, так что Document: IHtmlDocument2(3,4,5) будет уничтожаться только вместе с приложением Кроме того, как я уже писал в вопросе, всезнающий интернет рекомендует использовать как WB, так и EWB исключительно через их свойство ControlInterface. Но, если при использовании WB еще можно с этим смириться, то заниматься копипастом плюшек EWB, как, например, ExecScriptEx считаю излишним. |
| Автор: gonan 9.5.2017, 16:16 | ||
Подскажите как сделать "перебилд пакета", Что то не могу сообразить. Сам файл SHDocVw.pas (C:\Program Files (x86)\Embarcadero\Studio\16.0\source\internet) подправил. Компонент TWebBrowser Делфи XE8, Win 8.1 x64 |
| Автор: kami 14.5.2017, 20:06 | ||
Вам нужно сделать что-то из нижеперечисленного: 1. просто закинуть измененный pas-файл в папку с dproj-файлом вашего проекта. Этого будет достаточно. Учтите, что в этом случае вы привязываетесь к конкретной версии Delphi, при компиляции на другой версии потребуется удалить этот файл из папки с проектом, чтобы он не подхватывался автоматом. 2. Включить папку, в которой лежит измененный pas, в Project-Options-LibraryPath. Кажется, этого тоже будет достаточно, но можно попробовать поставить брейкпоинт в этом (обращаем внимание на пути!) файле (например - в конструкторе TWebBrowser) и убедиться, что остановка происходит. Т.е. берется именно измененный файл. 3. Если есть dcu измененного pas-файла, то можно заменить его в library-папке Delphi (нежелательно). Самый предпочтительный вариант, на мой взгляд - первый. Не стоит без очень весомого основания менять генофонд (т.е. исходные исходники). |
| Автор: gonan 15.5.2017, 21:44 | ||
Сделал по первому варианту. Исправленный файл SHDocVw.pas положил в папку с dproj-файлом проекта. Рядом с EXE появился файл SHDocVw.dcu. Но к сожалению не помогло. Память растёт. После 600-700 раз вызова метода WebBrowser1.Navigate и 1 ГБ уже обеспечен. А дальше вылетать начинает программа с ошибками. RAD Studio 10.1 Berlin |