Что нового

Скрипт поедает память. Как определить, почему?

Статус
Закрыто для дальнейших ответов.

bescom

Новичок
Сообщения
61
Репутация
0
Прошу меня простить за то, что не могу привести сам скрипт, ибо часть его используется в коммерческой программе. Ну, да не в этом суть.
Скрипт при запуске вместе со всеми подключаемыми компонентами занимает 7 мБ, но в процессе работы поедает память до возможного максимума и, как логическое завершение, выдает "Error allocating memory" примерно на 1.3 гБ.

Я перерыл документацию и форум, но все, что нашел по этому поводу, заключалось в следующем:

1. Если открываете файлы с помощью FileOpen, обязательно закрывайте посредством FileClose. Закрыл. Ситуация не изменилась

2. Все, что можно вынести в функции, нужно вынести, чтобы переменные обнулялись.. Вынес всё, что можно. Ситуация осталась прежней.

3. Нужно изучить FAQ по использованию ресурсов в AutoIt Изучил. Понял суть, но совершенно не понял, как практически применимо данное знание.

4. AutoIt все делает сам - очищает переменные, массивы и т.д., не парься из-за этого

Теперь, собственно, сам вопрос: Как определить, что в скрипте поедает память?
Как вариант - советы, на что обратить внимание, возможные причины. На форуме много тем, которые неоднократно описаны в виде "самые частые ошибки новичков в чем-то". Почему бы не собрать примерно то же самое по причинам неадекватного расходования скриптами памяти?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Причин может быть целый вагон и маленькая тележка. Вы не предоставили скрипт или его часть, не сказали что делает программа. Что же вы хотите? Перечислите хотя бы _WinAPI_* функции, которые вы используете и список подключаемых библиотек. Если ваша программа покрыта завесой тайны, то разбирайтесь сами. Советую наставить контрольных точек и смотреть в диспетчере задач, на какой стадии выполнения скрипта выделяется память.
 

Prog

Продвинутый
Сообщения
537
Репутация
65
Обычная утечка памяти или ресурсов ОС. Без кода ничего определенного не сказать. Проверьте чтобы все ресурсы запрошенные у ОС, освобождались.


bescom [?]
4. AutoIt все делает сам - очищает переменные, массивы и т.д., не парься из-за этого
Очень большое заблуждение!
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Prog сказал(а):
Очень большое заблуждение!
На самом деле, если используются только нативные функции AutoIt, то в боьшинстве случаев об освобождении пямяти думать не приходится, т.к. AutoIt не работает с хэндлами. Все ресурсы, на которые ссылаются локальные переменные, автоматически освобождаются при выходе из функции. Да, можно, конечно, перебрать память массивами или структурами, но это все частные случаи. Самая распространенная ошибка, это работа с GDI или GDI+.
 
Автор
bescom

bescom

Новичок
Сообщения
61
Репутация
0
Yashied сказал(а):
Причин может быть целый вагон и маленькая тележка. Вы не предоставили скрипт или его часть, не сказали что делает программа. Что же вы хотите? Перечислите хотя бы _WinAPI_* функции, которые вы используете и список подключаемых библиотек. Если ваша программа покрыта завесой тайны, то разбирайтесь сами. Советую наставить контрольных точек и смотреть в диспетчере задач, на какой стадии выполнения скрипта выделяется память.
Согласитесь, не всегда хочется светить код по разным причинам. Это как раз тот случай. Я поэтому и запросил общие советы.

Программа не использует _WinAPI_* функции. Библиотеки: InetConstants.au3, file.au3, FF.au3, String.au3, Array.au3, GUIConstants.au3.
Логика примерно такая. Скрипт запускает FireFox, подключается по MozRepl, и начинает в цикле перебирать URL-адреса из файла, загружая по очереди в браузер и считывая список ссылок со страницы в массив. Массив сохраняется в файл, в котором программа обнаруживает или не обнаруживает искомый адрес и по этому признаку помещает адреса страниц в тот или иной файл.

Насчет контрольных точек - мысль однако, что-то я не догадался...


Добавлено:
Сообщение автоматически объединено:

Prog сказал(а):
Проверьте чтобы все ресурсы запрошенные у ОС, освобождались.
Работаю именно в этом направлении. Но или не вижу чего-то лежащего на виду, или чего-то не знаю.

Prog сказал(а):
bescom [?]
4. AutoIt все делает сам - очищает переменные, массивы и т.д., не парься из-за этого
Очень большое заблуждение!
Я уже на опыте убедился, что это заблуждение, но такой совет присутствует на форуме. ;)
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
bescom,
Предупреждение За нарушение общих правил (пункт В.2):
Старайтесь избегать “Over quoting” (преувеличенное цитирование) - цитируйте только необходимую часть сообщения, которая наилучшим образом подчеркнёт суть цитируемого.


С уважением, ваш Глобальный модератор.
 
Автор
bescom

bescom

Новичок
Сообщения
61
Репутация
0
1. Прошу прощения, если невольно нарушил правила, постараюсь больше ни-ни... :smile:

2. С проблемой поедания памяти скриптом разобрался, и в очередной раз убедился - некоторые особенности работы функций AutoIt никак не описаны, к величайшему сожалению...

Yashied правильно сказал, что нужно расставить контрольные маячки - они позволили уже через несколько минут локализовать место возникновения проблемы, а там уже было дело техники и догадливости. Попробую на импровизированной схемке пояснить, что и как.

Было в одной из функций (последовательность):

Открытие файла №1
Работа с файлом №1
Открытие файла №2
Работа с файлом №2
Работа с файлом №1
Закрытие файла №1
Закрытие файла №2


В итоге один из них не закрывался, с каждым обращением к функции поедая от 2,5 до 20 мБ. Все пришло в норму после смены последовательности на:

Открытие файла №1
Работа с файлом №1
Открытие файла №2
Работа с файлом №2
Закрытие файла №2
Работа с файлом №1
Закрытие файла №1


В общем, открытие/закрытие файлов "вложенное" допускается, а "пересекающеесся" нет. Надеюсь, мой опыт кому-нибудь пригодится. Всем добра!!!
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
bescom, то, что вы описали, никак не может вызвать утечку памяти. Файлы можно открывать и закрывать в любой последовательности. Главное, чтобы количество открытий было равно количеству закрытий.
 
Автор
bescom

bescom

Новичок
Сообщения
61
Репутация
0
Yashied, это факт. Буквально переместил одну строку, и утечка исчезла.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
bescom сказал(а):
Yashied, это факт. Буквально переместил одну строку, и утечка исчезла.
Этого не должно быть. Возможно, была ошибка в названиях переменных, например, одна переменная для обоих файлов. Хотя, я и не исключаю какой-нибудь баг в AutoIt, но проверять лень.
 
Автор
bescom

bescom

Новичок
Сообщения
61
Репутация
0
Yashied, я сутки лопатил и перелопачивал код из трех сотен строк, перепроверил множество версий, и тоже считал, что порядок закрытия файлов не имеет значения. Вы как подсказали про маячки, я моментом вычислил место возникновения проблемы, а там грешить больше было не на что. Переменные и дескрипторы разные, да и всё остальное достаточно простое, то есть интуитивно понятное. Оставался под подозрением только порядок открытия/закрытия, и после перемещения строки закрытия одного из файлов все встало на места. Прямо сейчас скрипт тестируется уже на втором компьютере, и потребление памяти процессом не выходит за 20 мБ на шести сотнях обращений к функции.

Так что может, и нужны какие-то определенные условия для возникновения бага, но вот у меня они как раз сложились... ;)
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
bescom
рассуждать о вашей проблеме не видя кода - пустая трата времени. вы можете сколько угодно перемещать строки и говорить о результатах, но факт вот в чем
[?]
В итоге один из них не закрывался, с каждым обращением к функции поедая от 2,5 до 20 мБ
если не закрывать файл и при этом открывать его много раза(даже не важно один ли это и тот же файл), то потребление памяти будет увеличиваться
пока не увидим код , можно долго бла-блакать
 

CrazyDoc

Новичок
Сообщения
75
Репутация
2
и мне хотелось бы увидеть хотя бы шаблон этого куска кода. попробовал с excel, notepad - не наблюдал такого эффекта.
 
Автор
bescom

bescom

Новичок
Сообщения
61
Репутация
0
Старый вариант:

Код:
Func URLFromArray()
   Local $urlstr[1][1]
$fileopenstr = FileOpen(@ScriptDir&"\links_temp.txt",0)
$kolichestvostrokstr = _FileCountLines(@ScriptDir&"\links_temp.txt")

$nnn=1 ; Цикл перебора ссылок в из массива
Do
   $linenumstr = $nnn
   $linestr = FileReadLine($fileopenstr,$linenumstr)
   $urlstr = _StringBetween($linestr, "", "|")
   ; Проверка на присутствие в строке искомого домена
   $fileopen = FileOpen(@ScriptDir&"\domen.txt",0)
   $domen = FileReadLine($fileopen,2)

	If StringInStr($urlstr[0], $domen) = 0 Then
	   $nnn=$nnn+1
	   If $nnn = $kolichestvostrokstr+1 Then
		 ; MsgBox(0, "Ссылка не найдена!!!", "Ошибка!!! По адресу " & $line &@CRLF& " ссылка на домен " & $domen & " не найдена!")
		 ; Действия, если ссылка не найдена
			FileWriteLine(@ScriptDir&"\error_links.txt", $line)
		 ; Конец действий, если ссылка не найдена
		 ExitLoop
	   EndIf
	EndIf

    While StringInStr($urlstr[0], $domen) <> 0
	; MsgBox(0, "Ссылка найдена!!!", $urlstr[0])
	; Действия, если ссылка найдена
		 FileWriteLine(@ScriptDir&"\ok_links.txt", $line)
    ; Конец действий, если ссылка найдена
	ExitLoop
    WEnd

Until StringInStr($urlstr[0], $domen) <> 0

FileClose($fileopenstr)
FileClose($fileopen)
$urlstr=0
 EndFunc

Новый вариант:

Код:
Func URLFromArray()
   Local $urlstr[1][1]
$fileopenstr = FileOpen(@ScriptDir&"\links_temp.txt",0)
$kolichestvostrokstr = _FileCountLines(@ScriptDir&"\links_temp.txt")

$nnn=1 ; Цикл перебора ссылок в из массива
Do
   $linenumstr = $nnn
   $linestr = FileReadLine($fileopenstr,$linenumstr)
   $urlstr = _StringBetween($linestr, "", "|")
   ; Проверка на присутствие в строке искомого домена
   $fileopen = FileOpen(@ScriptDir&"\domen.txt",0)
   $domen = FileReadLine($fileopen,2)
   FileClose($fileopen)

	If StringInStr($urlstr[0], $domen) = 0 Then
	   $nnn=$nnn+1
	   If $nnn = $kolichestvostrokstr+1 Then
		 ; MsgBox(0, "Ссылка не найдена!!!", "Ошибка!!! По адресу " & $line &@CRLF& " ссылка на домен " & $domen & " не найдена!")
		 ; Действия, если ссылка не найдена
			FileWriteLine(@ScriptDir&"\error_links.txt", $line)
		 ; Конец действий, если ссылка не найдена
		 ExitLoop
	   EndIf
	EndIf

    While StringInStr($urlstr[0], $domen) <> 0
	; MsgBox(0, "Ссылка найдена!!!", $urlstr[0])
	; Действия, если ссылка найдена
		 FileWriteLine(@ScriptDir&"\ok_links.txt", $line)
    ; Конец действий, если ссылка найдена
	ExitLoop
    WEnd

Until StringInStr($urlstr[0], $domen) <> 0

FileClose($fileopenstr)
$urlstr=0
 EndFunc

А то не верите на слово... ;)
И прошу не сильно ругать за корявость кода...
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
bescom [?]
А то не верите на слово.

а что тут верить. все как и говорили - дескрипторы нужно закрывать а не гонять открытие в цикле
в первом варианте вот это было без закрытия.
Код:
$fileopen = FileOpen(@ScriptDir&"\domen.txt",0)

потом ты в цикле поставил закрытие вот и прошло поедание памяти. а лучше предыдущую строку вообще вынести из цикла.
правило такое - до всех циклов открыл все нужные файлы, после выхода из всех циклов - закрыл все открытые файлы и все. если бы сначала выложил проблемный код, то не нужно было бы на две страницы эпопею писать и вызывать кучу экстрасенсов ;)
и еще, не нужно вписывать флаг 0 при открытии. он и так по умолчанию
 
Автор
bescom

bescom

Новичок
Сообщения
61
Репутация
0
joiner, я так понимаю, Вы вообще не смотрели в код. В обоих вариантах оба дескриптора закрывались, только "с перехлестом", о чем я и написал.
И не нужно здесь сеять агрессию и сарказм, тема была про то, что по поводу поедания памяти нигде нет перечисления причин для неопытных программистов, к числу которых я причисляю и себя. Спрашивались общие советы, на что обратить внимание, а не конкретные указания в коде.
Я предполагал, что гуру AutoIT должен быть как-то подоброжелательнее, особенно при том, что невнимательно смотрит предоставленный код и делает неверные выводы.
И еще - не хотелось бы тут устраивать холивар.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
bescom [?]
Вы вообще не смотрели в код.
еще раз посмотри первый проблемный код и покажи, где в цикле было закрытие? я не пьян (несмотря на праздник)
насчет всего остального, если нужно решение, то сразу выкладывают проблемный код. А если хочется поболтать, то раздувают тему. я не гуру языка. а знаковое отличие ставится автоматом . такие вот пироги
 
Статус
Закрыто для дальнейших ответов.
Верх