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 |
procedure TForm9.Button1Click(Sender: TObject); var RusA: set of Char; Finput,Hinput,Tinput : File; Dialog : TOpenDialog; StrInput: array of Byte; Stmp,key: string; i,j,H,len,size,sizeedit: integer; Buff,shifr,Shifr2 : AnsiString; ok :boolean; begin RusA:=['A','B','C','D','E','F','0','1','2','3','4','5','6','7','9']; key:=edit1.text; sizeedit:=Length(edit1.text); for I := 1 to Sizeedit do begin if (key[i] in RusA) then ok:=true else ok:=false; end; if (ok=true) then begin //Ищем файл Progressbar1.Position:=0; ShowMessage('Откройте нужный файл!'); Dialog := OpenDialog1; if Dialog.InitialDir = '' then Dialog.InitialDir := ExtractFilePath( Application.ExeName ); if not Dialog.Execute then Exit; if not FileExists(Dialog.FileName) then begin MessageBox(0,'Файл не найден.','Файл не найден',MB_OK + MB_ICONWARNING + MB_APPLMODAL); Exit; end; //Присваиваем файлу имя AssignFile(Finput, Dialog.FileName); Progressbar1.Position:=20; Reset(Finput, 1); Size:= FileSize(Finput); If size<134217728 then begin /////////(это на время пока не исправлю ошибку с размерами) SetLength(StrInput, Size);//Задаем размер массива с размером файла BlockRead(Finput, StrInput[0], Size);//Считываем файл в строку байтов CloseFile(Finput); //Представляем строку байтов в виде HEX кода Len := Size * 3 + (Size div 16); Progressbar1.Position:=50; if Size mod 16 > 0 then Dec(Len); SetLength(HexInput, Len); H := High(StrInput); j := 1; for i := 0 to H do begin STmp := IntToHex(StrInput[i], 2); HexInput[j] := STmp[1]; HexInput[j + 1] := STmp[2]; Inc(j, 2); if i = H then Continue; if i mod 16 = 15 then begin HexInput[j] := #13; // probel HexInput[j + 1] := #10; //konec stroki Inc(j, 2); end else begin HexInput[j] := #9; //Tab Inc(j); end; end; Progressbar1.Position:=70; if checkbox1.Checked=true then Memo1.Text := HexInput; //чистый HEX Progressbar1.Position:=90; Shifr:=Viz_crypt(HexInput,Edit1.text); if checkbox1.Checked=true then Memo2.Text:=shifr; //кодированный HEX Shifr2:=getbytestr(shifr); AssignFile(hinput, Dialog.FileName+'.cry'); Rewrite(hinput, 1); BlockWrite(hinput, Shifr2[1], Length(Shifr2));//Считываем файл в строку символов Closefile(hinput); end else begin showmessage('Пожалуйста, выберите файл меньшего размера!');/////////(это на время пока не исправлю ошибку с размерами) Progressbar1.Position:=0; exit; end; end else showmessage('Пожалуйста, введите ключ содержащий только:A,B,C,D,E,F,0,1,2,3,4,5,6,7,9'); Progressbar1.Position:=100; ShowMessage('Готово!'); end; |
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS
Contact US
Thanks. We have received your request and will respond promptly.
Log In
Come Join Us!
Are you a
Computer / IT professional?
Join Tek-Tips Forums!
- Talk With Other Members
- Be Notified Of Responses
To Your Posts - Keyword Search
- One-Click Access To Your
Favorite Forums - Automated Signatures
On Your Posts - Best Of All, It’s Free!
*Tek-Tips’s functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.
Posting Guidelines
Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Students Click Here
«out of memory» exception«out of memory» exception(OP) 9 Aug 05 06:13 Hi all! I’m programming a very RAM-expensive thing and I’ve come over the following problem: Until now, when all available RAM was used up on my test machine, Windows started to swap and the application got very slow. All of a sudden, the swapping didn’t start any more when RAM was used up, but I always got the error «out of memory» (without further explanation and without hitting my app’s error log). At first I thought this was a Windows issue because I had played around with the swap file, but after a complete Windows reinstall it did not work either. Do you think this could be a program-caused error, or have you ever had it yourself? Thank you for any suggestions, Red Flag SubmittedThank you for helping keep Tek-Tips Forums free from inappropriate posts. |
Join Tek-Tips® Today!
Join your peers on the Internet’s largest technical computer professional community.
It’s easy to join and it’s free.
Here’s Why Members Love Tek-Tips Forums:
Talk To Other Members- Notification Of Responses To Questions
- Favorite Forums One Click Access
- Keyword Search Of All Posts, And More…
Register now while it’s still free!
Already a member? Close this window and log in.
Join Us Close
← →
TrueCoder
(2005-06-01 03:29)
[0]
Так как Delphi пользуюсь нечасто, возникла проблема, решить которую сам пока не могу. Поиск тоже ничего что-то не дал..
Объявлен тип, например: type TValues = array [0..8] of Variant;
Объявлен массив: Values: array of TValues;
Имеется счетчик элементов массива Values = Count: Integer.
Изначально массив пуст, значит Count=0.
Новые элементы массива Values добавляются в цикле по одному через SetLength(Values,Count+1). И все работает, до тех пор пока размер памяти, занимаемый приложением, не достигает 128 мегабайт. После чего, возникает ошибка «Out of memory».
Причем, размер оперативки в компе — 1 Гб, не говоря уже о виртуальной памяти. В момент возникновения ошибки оперативки свободно около 500 Мб. Выгрузка вообще всех других приложений тоже не помогает.
Вопрос — отчего возникает такая ошибка? Может я чего не понимаю в механизме выделения памяти? В хелпе имеется такая фраза по SetLength — «If there is not enough memory available to reallocate the variable, SetLength raises an EOutOfMemory exception», что у меня, похоже, и происходит. Но почему?!
ОС — WinXP Home, сама Delphi — семерка. Благодарю за любую помощь.
![]()
![]()
← →
Defunct ©
(2005-06-01 04:35)
[1]
Попробуйте заменить массив на TList, там SetLength используется немного не так как у вас.
![]()
![]()
← →
Digitman ©
(2005-06-01 08:45)
[2]
при очередном запросе Вorland Мemory Мanager»а на перераспределение памяти система не обнаружила в АП тек.процесса свободного региона затребованного размера и вернула отказ, о чем ВММ любезно и сообщил соотв.исключением
скорей всего АП процесса на момент отказа было сильно фрагментировано по причине предыдущих массированных «мелких» реаллокаций, инициированных вызовами SetLength()
![]()
![]()
← →
ANB ©
(2005-06-01 08:57)
[3]
> Digitman © (01.06.05 08:45) [2]
Имхо. Очень странно. Занято 128М. Дефрагментация, понятно, но у процесса 4Г адресного пространства. Как может не хватить ? Может проблема в стеке ?
![]()
![]()
← →
Anatoly Podgoretsky ©
(2005-06-01 09:06)
[4]
TrueCoder (01.06.05 03:29)
Где код?
![]()
![]()
← →
Bel ©
(2005-06-01 09:09)
[5]
> но у процесса 4Г адресного пространства
Причем, учти, из них половина отдана под ядро, а в оставшейся половине кроме данных твоего приложения располагаются exe-шник твоего приложения, а также все библиотеки. Плюс много других данных, используемых приложением. В итоге остается достаточно свободной памяти, но если расходовать ее неправильно, то и она может кончиться.
![]()
![]()
← →
ANB ©
(2005-06-01 09:16)
[6]
> Причем, учти, из них половина отдана под ядро
— Ну 2Г. Ну 500М накладные расходы (сроду столько не было). 1,5Г забить одним массивом ?
В принципе хороший совет — сначала определить максимальную длинну, а потом писать в массив, но он не всегда выполним. Например, я не всегда знаю заранее размер массива. В своем проекте у меня много мест, где длинна приращивается на 1, но на такую ошибку ни разу не нарывался. Ресурсы раз кончаться начали, но это я компонент кривой заюзал. Поменял на стандартный — ошибка ушла.
![]()
![]()
← →
Bel ©
(2005-06-01 09:21)
[7]
Дык, массив то должен занимать непрерывный участок памяти. Памяти то может быть и 1.5Г свободно, а вот непрерывного участка размером, допустим, 10М может не быть. Поэтому в данном случае уже предложили решение — использовать TList.
![]()
![]()
← →
evvcom ©
(2005-06-01 09:22)
[8]
Вообще подход действительно неверный. Реаллокэйтить такие массивы — это встретиться с жуткими тормозами из-за постоянного копирования «полезной» информации. Лучше использовать TList или цепочки.
![]()
![]()
← →
Digitman ©
(2005-06-01 09:22)
[9]
> ANB © (01.06.05 08:57) [3]
> Занято 128М
эта цифирь не имеет отношения к ВАП процесса
![]()
![]()
← →
ЮЮ ©
(2005-06-01 09:32)
[10]
Если человеку не нужны механизмы TList, то достаточно увеличивать длину массива так, как это сделано в TList.Grow, тем более, что количество действительных элементов массива он и так подсчитывает в Count
![]()
![]()
← →
ANB ©
(2005-06-01 09:32)
[11]
> эта цифирь не имеет отношения к ВАП процесса
— согласен. Но не полностью. Чем больше эта цифра, тем больше вероятности нарваться на конец памяти. Приплюсовать сюда дефрагментацию . . . Кстати, автор не дал код и не сообщил максимальную длинну своего массива.
![]()
![]()
← →
Mx ©
(2005-06-01 09:46)
[12]
Возник вопрос: а чем же TList лучше? В не тоже есть Realloc»и, хоть и реже вызываемые, но в итоге точно также потребуется большой объем памяти (правда Pointer меньше чем Variant, но это лишь вопрос количества элементов).
![]()
![]()
← →
Думкин ©
(2005-06-01 09:48)
[13]
> [12] Mx © (01.06.05 09:46)
хоть и реже вызываемые, — ты сказал(с)
![]()
![]()
← →
Mx ©
(2005-06-01 09:55)
[14]
> Думкин © (01.06.05 09:48) [13]
Вроде ошибка: Out of memory, а не Unable to Realloc? Не хватает, как я понял, объема, причем здесь количество реалокейтов?
![]()
![]()
← →
ANB ©
(2005-06-01 09:56)
[15]
Без кода и поллитры не разберемся.
![]()
![]()
← →
Думкин ©
(2005-06-01 10:05)
[16]
> [14] Mx © (01.06.05 09:55)
смотрим [2] Digitman © (01.06.05 08:45) — задумываемся.
![]()
![]()
← →
Mx ©
(2005-06-01 10:13)
[17]
> Думкин © (01.06.05 10:05) [16]
Я уже читал. Но: Дык, массив то должен занимать непрерывный участок памяти. Памяти то может быть и 1.5Г свободно, а вот непрерывного участка размером, допустим, 10М может не быть. Поэтому в данном случае уже предложили решение — использовать TList. © Bel. Ну допустим, Realloc не смог выделить память в текущем месте, я так понимаю занимаемую память он освободит, и будет выделен новый — бОльший участок в другом месте. Ну так и причем здесь количество Realloc»ов? Или он работает только «по возрастанию»? Т.е. в конце концов может «упереться в вершину» (извините, за образность)?
![]()
![]()
← →
evvcom ©
(2005-06-01 10:17)
[18]
> Mx © (01.06.05 10:13) [17]
Каков характер твоих данных? Необходим ли тебе доступ к произвольному элементу этого массива в любой момент времени? Или эти данные обрабатываются строго по порядку (сверху вниз или снизу вверх, не важно)?
![]()
![]()
← →
Mx ©
(2005-06-01 10:20)
[19]
У меня данных нет, почитал ветку и кое чего не понял, вот и спросил… вдогонку.
![]()
![]()
← →
evvcom ©
(2005-06-01 10:24)
[20]
Да, действительно… [18] должно быть адресовано TrueCoder
![]()
![]()
← →
Mx ©
(2005-06-01 10:31)
[21]
Продолжаю. Допустим у нас 20 ячеек памяти, каждая пятая занята. Тогда какая разница, что я «дойду» до необходимости выделения 6 смежных ячеек, а что я их сразу запрошу? Свободных то все-равно нет. Это я имел ввиду в вопросе.
![]()
![]()
← →
Digitman ©
(2005-06-01 10:33)
[22]
> Mx © (01.06.05 09:55) [14]
> Вроде ошибка: Out of memory, а не Unable to Realloc? Не
> хватает, как я понял, объема, причем здесь количество реалокейтов?
найти грабли достаточно легко — перехватываем точки входа в VirtualAlloc и LocalAlloc, протоколируем отказы этих вызовов
если отказал VirtualAlloc, грабли в дефрагментации и/или отсутствии региона нужного размера
если LocalAlloc, грабли — в исчерпании кучи
![]()
![]()
← →
Mx ©
(2005-06-01 10:38)
[23]
У меня примера нет. Может автор проверит?
![]()
![]()
← →
Digitman ©
(2005-06-01 10:41)
[24]
getmem.inc наглядно показывает grow-механизм работы ВММ — сначала в АП резервируется регион, а затем идет запрос к дифолтной куче
а в целом грабли даже и искать не нужно
лезем в sysutils.pas, видим там
EOutOfMemory = class(EHeapException);
т.е. отказ вернула ф-ция LocalAlloc из-за исчерпания кучи
![]()
![]()
← →
Mx ©
(2005-06-01 10:43)
[25]
Как на это влияет число вызовов ReallocMem?
![]()
![]()
← →
Digitman ©
(2005-06-01 11:00)
[26]
вот так и влияет
AddBlockAfter() вызывает LocalAlloc() посредством GetBlockDesc(), запрашивая из кучи блок памяти, а DeleteBlock() назад в кучу его не отдает
![]()
![]()
← →
Mx ©
(2005-06-01 11:32)
[27]
Все-равно не понимаю. Если я запрошу блок вначале 1*Integer, потом 2*Integer, потом 3*Integer. А если запрошу сразу 3*Integer, то что выиграю? И в том и в другом случае я запрашиваю 3*Integer ячеек. А! В первом случае получается 6*Integer, да? Правильно понял? Т.е., высвобождая предыдущий блок, ReallocMem не далает эти ячейки доступными для следующего Realloc»а?
![]()
![]()
← →
Digitman ©
(2005-06-01 11:58)
[28]
> Mx © (01.06.05 11:32) [27]
> Если я запрошу блок вначале 1*Integer, потом 2*Integer,
> потом 3*Integer.
.. то потенциально возможны три вызова LocalAlloc() при ни одном LocalFree()
А если запрошу сразу 3*Integer, то что
> выиграю?
при этом будет не более чем один LocalAlloc()
ВММ оперирует понятием и механизмом «блок»
у каждого блока есть упр.структура для организации связного двунапр.списка из блоков, хранения атрибутов («свободен», «занят»), адреса, где размещены собственно данные блока, если блок занят, и размера.
когда прикл.код обращается к ВММ за выделением памяти, ВММ ищет первый своб.блок минимально подходящего размера и помечает его как «занятый», манипулируя далее с соотв.регионами в АП процесса (1)
если своб.блок не найден, ВММ запрашивает из кучи фрагмент размера равного заголовку блока и затем выполняет (1)
когда прикл.код обращается к ВММ за освобождением памяти, ВММ ищет заголовок блока по полю размера, помечает этот блок как свободный, НЕ отдавая в кучу память, ранее запрошенную под этот блок, и далее опять же манипулирует соотв.регионами
реаллокация у ВММ — более сложный алгоритм (с т.з. манипуляций регионами), но сводится он опять же к аллокации нового и деаллокации прежнего блока
ну это так, сильно упрощенная схема …
детали же реально происходящего — в getmem.inc
![]()
![]()
← →
Mx ©
(2005-06-01 12:35)
[29]
Как все запушено… Спасибо, на досуге повнимательнее почитаю getmem.inc.
![]()
![]()
← →
TrueCoder
(2005-06-01 16:38)
[30]
Большое спасибо всем ответившим. Даже не ожидал, что моя проблема поднимет такую дискуссию. Есть о чем подумать.
Трезвую мысль высказал Digitman: «Cкорей всего АП процесса на момент отказа было сильно фрагментировано по причине предыдущих массированных мелких реаллокаций, инициированных вызовами SetLength()». Интуитивно чувствую, что истина где-то тут.
Код привести, к сожалению, не могу, запутанный он. Там долго и нудно обрабатываются Variant-ячейки таблицы ExpressQuantumGrid (штука классная, но сложнаяяяя..). Исключение возникает при обработке порции порядка 5 тысяч записей, но записи большие, в каждой по 50 полей, большинство текстовые, разной длины, поэтому я даже затруднюсь сказать максимальный размер массива.
Главное, что я понял — ошибка где-то в самом коде. Точнее, даже не в коде, а в самом принципе использования памяти — не любит ОНО многочисленных мелких реалокаций. Буду думать, может TList прикрутить получится.
Насторожило то, что исключение возникает при объеме памяти, занимаемого приложением, в 128 Мб. По неопытности и подумал, может по умолчанию при компиляции какие ограничения существуют. А нет, чуда не произошло. 🙂
![]()
![]()
← →
Digitman ©
(2005-06-01 17:05)
[31]
> TrueCoder (01.06.05 16:38) [30]
> Трезвую мысль высказал Digitman
да ну нет)… на более пристальный взгляд она не такая уж и трезвая оказалась ..
EOutOfMemory = class(EHeapException);
т.е. отказ этот вызван исчерпанием хипа, а с хипом работает LocalAlloc, а LocalAlloc вызывается для аллокации памяти под заголовок блока, а не под сами данные, на которые занятый блок ссылается
отсюда и вывод напрашивается — с дефрагментацией АП еще бабушка надвое сказала, а вот хип опустошен тобой множеством реаллокаций по самое нехочу
> Буду думать, может TList прикрутить получится
ТЛист пользует тот же менеджер памяти, разница лишь в grow-алгоритме : ТЛист при добавлении эл-та списка запрашивает память сразу под несколько (не помню сколько — см. код класса) элементов, т.о. минимизируя число вновь создаваемых блоков и, соответственно, новых аллокациий в хипе
рано или поздно и с ТЛист можно нарваться на ту же ситуацию
> Насторожило то, что исключение возникает при объеме памяти,
> занимаемого приложением, в 128 Мб
а ты не гадай !
ты проверь или отвергни предположение насчет хипа ..
сразу после старта приложения запроси у системы хэндл дифолтного хипа своего процесса (GetProcessHeap) и тут же просканируй хип (HeapWalk)
а потом перед каждой своей итерацией, где ты реаллокируешь свой массив, делай тоже самое и следи за тем как изменяется состояние хипа
![]()
![]()
← →
Anatoly Podgoretsky ©
(2005-06-01 20:40)
[32]
Digitman © (01.06.05 17:05) [31]
ТЛист пользует тот же менеджер памяти, разница лишь в grow-алгоритме : ТЛист при добавлении эл-та списка запрашивает память сразу под несколько (не помню сколько — см. код класса) элементов, т.о. минимизируя число вновь создаваемых блоков и, соответственно, новых аллокациий в хипе
И не запомнишь, у него адаптирующий алгоритм, с переменным количеством сколько. Вроде бы каждое увеличение на 25% от текущего размера блока, чем больше запрашиваешь, чем больше получаешь.
![]()
![]()
← →
Defunct ©
(2005-06-02 01:21)
[33]
Anatoly Podgoretsky © (01.06.05 20:40) [32]
> разница лишь в grow-алгоритме
Не только. TList также был предложен по той причине, что размер непрерывного участка памяти при использовании TList будет минимально возможным, без переделывания логики программы.
![]()
![]()
← →
TrueCoder
(2005-06-03 23:39)
[34]
Наверное, никому уже не интересно, но все же расскажу. Анализом кода удалось найти возможность заранее вычислять размер будущего массива, поэтому число реалокаций с 5 тысяч удалось снизить до двух. И проблема отпала сама собой.
Конечно, текущее решение значительно более красивое, как с точки зрения чистого кодинга, так и с точки зрения полученного удовлетворения от красивого решения проблемы :), но, все же, осталось некоторое удивление. Разве, стабильно работающая система (я о менеджере памяти Delphi и о самой операционке) не должны стабильно работать и при условии пусть некрасивых, но все же верных решений. Таких как 5 тысяч мелких реалокаций памяти у меня ранее. Что-то все же неладно в данном королевстве..
Интерес остался, конечно, исключительно чисто теоретический, проверять почему не работало раньше банально нет времени.
![]()
![]()
← →
Defunct ©
(2005-06-04 02:53)
[35]
> TrueCoder
Проблема фрагментации — вечная проблема. Менеджер памяти пойдет в ущер скорости исполения, если будет заниматься постоянной дефрагментацией.
Поэтому делайте всегда всё красиво.
![]()
![]()
Hey there,
I needed a code to act like a bruteforcer so I found one, but the problem is I don’t want to use TStringList, so I replaced it with array of strings and added some modifications.
The problem is when I run the code, after a certain time I get «Out Of Memory» error.
I hope someone can show me where is my error, I use FreeMem and SetLength to free the array of string each iteration.
Code is below..
Regards
function bruteforce(astring: string ;substr: string ; startlen: integer;
endlen: integer): LongInt;
var i,n,x: integer;
bi,bc,br:integer;
npw: string ;
counter:integer;
bhlplst: array of string;
bcluster : array of string;
bresults : array of string;
label step1;
begin
bi := 0;
bc := 0;
br := 0;
//hlplst := TStringList.Create; //The left column
//cluster := TStringList.Create; //The middle section
//results := TstringList.Create; //The combinations created
for x := 1 to length(substr) do begin
//hlplst.Add(substr[x]);
SetLength(bhlplst, bi + 1);
bhlplst[bi] := substr[x];
Inc(bi);
end ;
step1:
for i := 0 to {hlplst.Count}bi - 1 do begin
for n := 1 to length(astring) do begin
//npw := hlplst.strings[i]+astring[n];
npw := bhlplst[i] + astring[n];
//cluster.Add(npw);
SetLength(bcluster, bc + 1);
bcluster[bc] := npw;
Inc(bc);
if length(npw) >= startlen then
begin
//results.Add(npw);
//SetLength(bresults,br + 1);
//bresults[br] := npw;
//Inc(br);
Form1.Memo1.Lines.Add(npw);
end;
end ;
end ;
//hlplst.clear;
bi := 0;
SetLength(bhlplst, bi);
FreeMem(bhlplst);
//hlplst.addstrings(cluster);
SetLength(bhlplst, bc );
for counter := 0 to bc - 1 do
begin
bhlplst[bi] := bcluster[counter];
Inc(bi);
end;
//cluster.Clear;
bc := 0;
SetLength(bcluster, bc);
FreeMem(bcluster);
if length(npw) + 1 <= endlen then goto step1;
//hlplst.Clear;
bi := 0;
SetLength(bhlplst,bi);
FreeMem(bhlplst);
result := 0;
end ;
Open in new window