![]() |
|
|
![]()
|
|
| Bima |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
Есть программа, которая читает данные по протоколу SNMP (компонент Indy: TIdSNMP) и передает эти данные в SCADA систему WinCC через DLL.
Программа работает стабильно (текущий вариант), но меня смущает то, что за пару месяцев работы, память занимаемая программой увеличивается и если программу свернуть и потом развернуть, то память сбрасывается, но потом по новой возрастает. Один раз было так, что на сервере выскочило сообщение, что вся виртуальная память занята. Хочу дороботать программу, что бы она работала стабильнее, поэтому спрашиваю совета у ВАС. Принимается любая критика. код программы: модуль kod.cpp:
Могу пояснить любой участок кода, так как сам писал программу. Заранее спасибо за советы -------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
|||
|
||||
| Bima |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
в первом сообщении не поместился Модуль kod.h:
-------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
|||
|
||||
| pandrew |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 213 Регистрация: 27.3.2006 Репутация: 3 Всего: 3 |
Кто же будет разбираться в чужом хламе такого размера?
Установи BoundsChecker или что-нибудь подобное и следи за утечками. |
|||
|
||||
| ama_kid |
|
||||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 10 Всего: 95 |
Bima
Хм... Я думаю, ты и сам понимаешь, что на таком коде сложно делать визуальную отладку. Было бы, конечно, лучше, чтобы ты прикрепил целиком проект с библиотекой (у меня, допустим, WinCC нет, я работаю с другими SCADA). Но вот так навскидку вопрос: почему у тебя в Form1Activate делается такая куча действий? К примеру каждый раз при активации формы у тебя загружается библиотека, каждый раз запускается функция Potok(); создающая потоки каждый раз. В общем, я не совсем это понимаю... Ну и по мелочам: 1) Вот этот код я не понял:
Первый цикл вообще бесполезный ибо не убивает потоки. FreeOnTerminate - это свойство, указывающее на возможность автоматического освобождения ресурсов при завершении потока. Следовательно, Sleep бесполезен, лучше его поставить после второго цикла, а первый вообще убрать. А еще лучше использовать не Sleep, а WaitForSingleObject или WaitForMultipleObjects 2) Вот здесь (при создании потоков):
Ну и, думаю, если серьезно покопать, можно найти еще несколько не совсем корректных действий, приводящих к возможным утечкам памяти... Но опять же - визуально это достаточно сложно сделать... -------------------- самурай без меча подобен самураю с мечом, но только без меча |
||||
|
|||||
| Bima |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
for pandrew
Я вообще предлагал другое, не разбираться в моей программе, а показать, как можно сделать некоторые участки кода по другому. Я практически уверен, что большинство кода, который написан выше - неоптимальный. Утечки памяти пробовал отслеживать на CodeGuard, но мне там не совсем понятно, как и что отслеживается. По поводу "такого размера"... если писать код кусками в каждой новой теме, то не всегда понятен смысл всей программы, да и оптимизация будет только на уровне блока, а не на уровне всей программы. Этот вариант уже проходил, так как многие куски кода, которые используются в этой программе, взяты именно с ответов этого форума. for ama_kid
Ставил прерывание на Form1Activate, оно выполняется только один раз.... может я ошибаюсь, но помоему, оно выполняется только один раз при запуске приложения
Я пытался там написать MyTh[i]->Terminate=true; , но у меня приложение при завершении выскакивало с ошибкой.
Для примера, как написать завершение потоков с помощью WaitForSingleObject или WaitForMultipleObjects???
Да здесь я ошибся, писал на автомате, думая, что задав true, у меня сразу запустится поток. Логика у меня такая: создается поток, присваивается ему значения, а потом запускается в нужный момент. Выкладываю весь проект здесь. Присоединённый файл ( Кол-во скачиваний: 7 )
Test_SNMP_WinCC9.rar 56,10 Kb-------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
||||||||
|
|||||||||
| ama_kid |
|
||||||||||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 10 Всего: 95 |
-------------------- самурай без меча подобен самураю с мечом, но только без меча |
||||||||||
|
|||||||||||
| Bima |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
выкладываю.
Да, я читал про это, но на практике, сколько бы раз я ее не сворачивал разварачивал... не передавал фокус на другое окно, все равно, OnActivate выполняется только при загрузке формы.
хм... поток не завершился, и что после этого делать.... убивать его принудительно??? Присоединённый файл ( Кол-во скачиваний: 6 )
add.rar 1,16 Kb-------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
||||||
|
|||||||
| pandrew |
|
||||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 213 Регистрация: 27.3.2006 Репутация: 3 Всего: 3 |
Поток надо так написать, чтобы он когда-нибудь завершился. А так после Terminate() вызываешь WaitFor() и зануляешь указатель на поток.
Тогда, по крайней мере, AV не получишь. |
||||
|
|||||
| Bima |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
на уровне простого програмирования (имеется ввиду внутренние объекты компьютера), выходит, что нужно так писать, но когда в потоке задействовано опрос какой нибудь внешней железки, которая может просто напросто не ответить или связь оборвется, в этом случае поток может просто напросто висеть, и завершать его все равно придется принудительно (это я пишу только для закрытия программы). по поводу кода, я такой уже встречал здесь, там как раз ругаются на такой алгоритм. -------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
|||
|
||||
| pandrew |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 213 Регистрация: 27.3.2006 Репутация: 3 Всего: 3 |
Я работаю много лет с разными железками подключенными к ПК (RS-232, USB, TCP/IP). Поверь на слово, есть в WinAPI все функции для опроса железяк, в которых невозможно зависнуть навсегда. Проблема сводится к выбору адекватного таймаута. А по поводу ругани и здесь было (якобы к моменту WaitFor переменная потока уже неадекватна), но у меня все годами работает в сотнях экземплярах, т.е. в этом месте проблем не встречал. |
|||
|
||||
| Bima |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
поробовал код:
Получил висящее приложение. Окно программы закрылось, а в памяти процесс остался. Если запускать в среде разработки ВСВ, то видно, что программа не отработала. Пытался делать
получил ошибки:
строка 81, это как раз строка с if -------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
||||||||
|
|||||||||
| ama_kid |
|
||||||||
![]() АСУТП-кодер ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1460 Регистрация: 5.3.2007 Где: Москва Репутация: 10 Всего: 95 |
Но это все лирика, бог с ними, с самими потоками... На самом деле, мне кажется, в данном случае надо смотреть еще глубже - в функции, с которыми потоки работают... И вот тут есть самое главное замечание, которое я могу высказать - это... Хм, я лучше процитирую хелп к функции Execute объекта потока:
-------------------- самурай без меча подобен самураю с мечом, но только без меча |
||||||||
|
|||||||||
| Bima |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
Очень конструктивная критика 1) в пределах объекта потока я НЕ вызываю компонеты из главной формы. Для передачи данных у меня существует блок TBlockList* Data, с критической секцией на доступ. Для записи лог файла, я использую тоже критическую секцию, так что здесь затыков не должно быть. 2) если делать один поток и постоянно перенастраивать сетевые компонеты, то скорость сильно падает в зависимости от количества устройств. Допустим у меня есть 10 железяк с опросом в 1 секунду, если опрос нормальный, то он занимает до 100 мс, следовательно при нормальном опросе 10 устройств займет 1 сек, а если мне нужно опросить больше? Все это при нормальном опросе, а если хотя-бы пару железяк зависло, то при опросе сработает тайм-аут (около секунды) и опрос 10 железок займет время больше 2 сек, что выходит за рамки задачи. При распараллеливании запросов (много потоков) все запросы выполняются в течении 1 секунды, даже если устройства зависли. 3) можно конечно сделать отдельный поток при пересылке тэгов в WinCC, но пока я не вижу в этом особого смысла, так как множество потоков придется синхронизировать с еще одним. Сегодня установил, что утечки памяти как раз идут при вызове функций Dll. сделал это следующим образом - заремировал все функции DLL и запустил программу, память ее не изменилась за несколько часов, а память программы с работающими функциями dll изменялась в большую сторону. По поводу пересмотреть структуру приложения - пока у меня доводов мало (из тех, что мне привели). Я как раз пришел к той, что есть сейчас из за быстродействия данной структуры. По поводу Suspend(); - это я не учел, сегодня подумаю. На вскидку, наверно нужно сначала запустить завершение потока, потом сделать ему Resume(); и следом все остальное. -------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
|||
|
||||
| Bima |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 518 Регистрация: 15.8.2006 Репутация: 2 Всего: 2 |
Очень конструктивная критика 1) в пределах объекта потока я НЕ вызываю компонеты из главной формы. Для передачи данных у меня существует блок TBlockList* Data, с критической секцией на доступ. Для записи лог файла, я использую тоже критическую секцию, так что здесь затыков не должно быть. 2) если делать один поток и постоянно перенастраивать сетевые компонеты, то скорость сильно падает в зависимости от количества устройств. Допустим у меня есть 10 железяк с опросом в 1 секунду, если опрос нормальный, то он занимает до 100 мс, следовательно при нормальном опросе 10 устройств займет 1 сек, а если мне нужно опросить больше? Все это при нормальном опросе, а если хотя-бы пару железяк зависло, то при опросе сработает тайм-аут (около секунды) и опрос 10 железок займет время больше 2 сек, что выходит за рамки задачи. При распараллеливании запросов (много потоков) все запросы выполняются в течении 1 секунды, даже если устройства зависли. 3) можно конечно сделать отдельный поток при пересылке тэгов в WinCC, но пока я не вижу в этом особого смысла, так как множество потоков придется синхронизировать с еще одним. Сегодня установил, что утечки памяти как раз идут при вызове функций Dll. сделал это следующим образом - заремировал все функции DLL и запустил программу, память ее не изменилась за несколько часов, а память программы с работающими функциями dll изменялась в большую сторону. По поводу пересмотреть структуру приложения - пока у меня доводов мало (из тех, что мне привели). Я как раз пришел к той, что есть сейчас из за быстродействия данной структуры. По поводу Suspend(); - это я не учел, сегодня подумаю. На вскидку, наверно нужно сначала запустить завершение потока, потом сделать ему Resume(); и следом все остальное. -------------------- Чтобы дойти до цели, надо идти. Клавиатура и мышь - это главные инструменты прогресса. |
|||
|
||||
| pandrew |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 213 Регистрация: 27.3.2006 Репутация: 3 Всего: 3 |
Самый простой довод "за": ты вынужден искать ошибку в куче кода (и нам пытался подсунуть). В правильной проге "критический" участок быстро локализуется. А быстродействием надо заниматься после верификации.
|
|||
|
||||
![]()
|
| Правила форума "С++ Builder" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C++ Builder | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |