Out of memory ошибка delphi

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;

Можно работать через TStreamReader и TStreamWriter. При некоторых условиях скорость работы может быть больше до 3х раз, чем по-старинке с readln и writeln:

var
  s:string;
  reader:TStreamReader;
  writer:TStreamWriter;

begin
   reader:=TStreamReader.Create(OpenDialog1.FileName, TEncoding.ANSI); // Если нужна другая кодировка - сменить
   writer := TStreamWriter.Create('out.txt', false,TEncoding.ANSI); // если нужно дописать файл, ставим True вместо false
   while not reader.EndOfStream do
     begin
        s:=reader.ReadLine;
        // делаем, что нужно с s
        writer.WriteLine(s); 
     end;
   // не забываем закрыть оба файла:
   reader.Free;
   writer.Free;
end;

Если же нужно обязательно хранить все строки в памяти, стоит работать через, например, TMemoryStream или TBytesStream, но стоит помнить, что в 32-битном режиме их емкость ограничена чуть менее, чем 2 Гб, а в 64-битном режиме, если надо > 2 Гб, с ними можно нормально работать только, начиная с Delphi Tokyo, или же делать патч.

Go Up to Error and Warning Messages (Delphi)

You get this error when the RAD Studio built-in compiler runs out of memory.

This is a rare error that might occur when you build an extremely large project group of applications and libraries.

To solve this issue, do any of the following:

  • Make sure your swap file is large enough and that there is still room on your disk. See Change the size of virtual memory.
  • Configure your project group to be built externally to the IDE: Select Project > Options > Delphi Compiler and check the Use MSBuild externally to compile property.
    Note: If you want to be able to debug your app when you build with this option set, the Include remote debug symbols option should also be enabled on Project > Options > Delphi Compiler > Linking.
  • Build your project group on the command line.
  • Refactor the applications and libraries in your project group to rely more on Delphi packages. Delphi packages do not make the IDE run out of memory.

 
Хост
 
(2008-12-29 05:23)
[0]

Когда массиву задаёшь слишком большие размеры, то не редко появляется такое сообщение. Нет ли какой-нибудь функции, чтобы заранее проверять есть достаточно памяти или нет?


 
Джо ©
 
(2008-12-29 07:00)
[1]

try/except с проверкой на EOutOfMemory.


 
Хост
 
(2008-12-29 07:34)
[2]


> Джо ©   (29.12.08 07:00) [1]
>
> try/except с проверкой на EOutOfMemory.

А как без try/except?

После try/except происходит выход из всех функций.


 
sniknik ©
 
(2008-12-29 08:05)
[3]

> А как без try/except?
никак. это единственный надежный способ.

> После try/except происходит выход из всех функций.
не происходит. см. 17ю строку.


 
Рамиль ©
 
(2008-12-29 09:04)
[4]

Это же сколько надо запросить, что бы получить EOutOfMemory?


 
test
 
(2008-12-29 09:07)
[5]

Хост   (29.12.08 07:34) [2]
try
…….
//какой то код
…….
except
on  EOutOfMemory do ShowMessage(«Не хватает памяти»);
ShowMessage(«Другие исключения»);
end;

Может в таком случае попробовать двунаправленный связанный список?


 
Хост
 
(2008-12-29 10:49)
[6]


> test   (29.12.08 09:07) [5]
>
> Хост   (29.12.08 07:34) [2]
> try
> …….
> //какой то код
> …….
> except
> on  EOutOfMemory do ShowMessage(«Не хватает памяти»);
> ShowMessage(«Другие исключения»);
> end;
>
> Может в таком случае попробовать двунаправленный связанный
> список?

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


> Рамиль ©   (29.12.08 09:04) [4]
>
> Это же сколько надо запросить, что бы получить EOutOfMemory?
>

В памяти программа занимает 1500 что ли мегабайт. Хотя предел — в районе трёх гигов. Так, что не понимаю, чего ей там не хватает. Наверное просто какое-то неправильное распределение памяти.


 
Jeer ©
 
(2008-12-29 10:59)
[7]


> В памяти программа занимает 1500 что ли мегабайт.

Видео напихал, наверное.


 
Slym ©
 
(2008-12-29 11:16)
[8]

Jeer ©   (29.12.08 10:59) [7]
расчет траекторий разлета частиц в БАКе с точностью 1/10000 периода полураспада бозона Хигса


 
Anatoly Podgoretsky ©
 
(2008-12-29 11:32)
[9]

> Хост  (29.12.2008 5:23:00)  [0]

Ну и какая разница? Чем текущая не устраивает?


 
Anatoly Podgoretsky ©
 
(2008-12-29 11:35)
[10]

> Хост  (29.12.2008 10:49:06)  [6]

Ты в курсе, что ограничение 2 гб?


 
Правильный$Вася
 
(2008-12-29 12:14)
[11]

не делать полимультимногократно SetLength
выставить максимальный размер сразу


 
test
 
(2008-12-29 12:18)
[12]

Правильный$Вася   (29.12.08 12:14) [11]
Тогда можно вообще массив обычный создать.


 
asail
 
(2008-12-29 12:36)
[13]


> Может в таком случае попробовать двунаправленный связанный
> список?

Памяти жрать есче больше будет (8 байт на указатели для каждого элемента). А, если у него там 1.5 гига массив из интежеров, например, то ваще каюк.
К тому-же если нужен прямой доступ к любому элементу массива, то при таком кол-ве элементов — каюк в квадрате.


 
StriderMan
 
(2008-12-29 12:36)
[14]

храните сразу на диске. все равно в своп все свалится. (если конечно не на серьезном сервере запускать)


 
asail
 
(2008-12-29 12:40)
[15]


> В памяти программа занимает 1500 что ли мегабайт. Хотя предел — в районе трёх гигов. Так, что не понимаю, чего ей там не хватает.

Насколько я в курсе, при SetLength, ищется НЕПРЕРЫВНЫЙ свободный участок памяти нужного объема… В случае сильной фрагментации его может и не оказаться.


 
Правильный$Вася
 
(2008-12-29 13:06)
[16]


> Тогда можно вообще массив обычный создать.

если время жизни данных в массиве равно времени жизни программы, то да
если же массив нужен ненадолго, то лучше не надо обычного


 
Servy ©
 
(2008-12-29 14:38)
[17]

> В памяти программа занимает 1500 что ли мегабайт. Хотя предел
> — в районе трёх гигов.

Предел в районе двух гигов. Чтобы сделать предел в районе трех гигов, необходима Win XP и выше, в boot.ini поставить параметр /3Gb и в PE заголовке твоего exe файла поставить отметку о том, что программа поддерживает больше двух гигабайт памяти. Подробности в гугле.


 
Jeer ©
 
(2008-12-29 16:55)
[18]


> Предел в районе двух гигов. Чтобы сделать предел в районе
> трех гигов, необходима Win XP и выше,

Я тебя уверяю, что даже Windows NT ent.srv. имел возможность работы с памятью объемом до 3 Gb. Не говоря уж о W2k adv.srv, который имеет возможность использования механизма PAE для доступа к объему выше 4Gb
Пример для w3:

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)WINDOWS=»Windows Server 2003, Enterprise» /fastdetect /PAE


 
Anatoly Podgoretsky ©
 
(2008-12-29 17:01)
[19]

> Jeer  (29.12.2008 16:55:18)  [18]

Без разницы, Дельфи просто не использует свыше 2 гб, как только это случается происходит Out of memory


 
Правильный$Вася
 
(2008-12-29 17:03)
[20]


> даже Windows NT ent.srv. имел возможность работы с памятью
> объемом до 3 Gb. Не говоря уж о W2k adv.srv

серверные операционки устроены несколько иначе в этом плане


 
Jeer ©
 
(2008-12-29 17:03)
[21]


> Без разницы, Дельфи просто не использует свыше 2 гб,

Использовать DLL на Си :)

или по Корану запрещено ?


 
Jeer ©
 
(2008-12-29 17:08)
[22]


> Правильный$Вася   (29.12.08 17:03) [20]

Между прочим, XP SP2 не поддерживает механизм PAE в отличии от SP1 :))


 
Рамиль ©
 
(2008-12-29 17:13)
[23]


> Между прочим, XP SP2 не поддерживает механизм PAE в отличии
> от SP1 :))

Не то что бы не поддерживает. Поддерживает, но требует указания в boot.ini ;)


 
Jeer ©
 
(2008-12-29 17:18)
[24]

Причина

Эта проблема возникает из-за изменения в Windows XP с пакетом обновления 2 (SP2), которое также содержится и в Windows Vista. В режиме PAE для улучшения совместимости драйверов были сделаны изменения. Для устранения проблем совместимости в Windows XP с пакетом обновления 2 (SP2) внесены изменения в слой абстрагирования оборудования (HAL), имитирующие поведение 32-разрядного прямого доступа к памяти слоя HAL. При этом в режиме РАЕ измененный HAL выделяет неограниченное число регистров отображения, а диспетчер памяти ядра игнорирует физические адреса за пределами диапазона 4 ГБ. Любая системная оперативная память, размер которой превышает 4 ГБ, не сможет быть адресована Windows и использована системой. Из-за ограничения адресного пространства до 4 ГБ устройства с 32-разрядной шиной прямого доступа к памяти не будут распознавать транзакции с адресами, лежащими за пределами 4 ГБ. Так как эти изменения ликвидируют необходимость в транзакциях с двойной буферизацией, они помогают исключить появление целого класса ошибок, относящихся к правильности реализации двойной буферизации в некоторых драйверах.
Основная проблема совместимости драйверов связана с использованием режима РАЕ в 32-разрядных системах. Режим PAE позволяет процессору адресовать более чем 4 ГБ памяти. Основное отличие между схемами разбиения памяти на страницы в PAE и не в PAE заключается в дополнительном уровне разделения, необходимом в режиме PAE. В режиме PAE требуются три уровня разбиения памяти на страницы вместо двух.
Если включен режим расширения физических адресов, некоторые драйверы не загружаются, поскольку устройство не поддерживает 64-разрядную адресацию или драйвер полагает, что режим расширения физических адресов требует более 4 ГБ оперативной памяти. Такой драйвер исходит из того, что в режиме расширения физических адресов будут поступать только 64-разрядные адреса, которые он (или соответствующее устройство) не в состоянии обрабатывать.
Другие драйверы загружаются в режиме РАЕ, но нарушают стабильность системы, пытаясь напрямую изменять записи в системной таблице страниц (PTE). В режиме РАЕ такие драйверы вместо ожидаемых 32-разрядных записей получают 64-разрядные записи таблицы страниц.
Наибольшая трудность связана с прямым доступом к памяти (DMA) и выделением реестров отображения. Многие устройства, которые поддерживают прямой доступ к памяти (как правило, 32-разрядные адаптеры), не могут выполнять 64-разрядную физическую адресацию. Если устройство запущено в 32-разрядном режиме, ему доступен весь диапазон физических адресов. В режиме расширения физических адресов данные могут располагаться по физическим адресам за пределами диапазона в 4 ГБ. Для включения устройств с этими ограничениями, семейство Windows 2000 Server и более поздние версии Windows снабжены системой двойной буферизации транзакций DMA. Семейство Windows 2000 Server и более поздние версии Windows осуществляют это с помощью передачи 32-битного адреса, указанного в регистре отображения. Устройство выполняет операцию DMA с 32-разрядным адресом, а ядро копирует память по 64-разрядному адресу, который выделен драйверу. Если режим РАЕ выключен, драйверам 32-разрядных устройств не требуется поддержка регистров отображения со стороны реальной памяти, т. е. двойная буферизация не нужна, поскольку все устройства и драйверы располагаются в 32-разрядном диапазоне адресов. В результате тестирования драйверов 32-разрядных устройств на компьютерах с 64-битной архитектурой процессоров выяснилось, что большинство драйверов с поддержкой прямого доступа к памяти используют неограниченные регистры отображения.


 
Хост
 
(2008-12-30 01:27)
[25]


> Servy ©   (29.12.08 14:38) [17]
>
> > В памяти программа занимает 1500 что ли мегабайт. Хотя
> предел
> > — в районе трёх гигов.
>
> Предел в районе двух гигов. Чтобы сделать предел в районе
> трех гигов, необходима Win XP и выше, в boot.ini поставить
> параметр /3Gb и в PE заголовке твоего exe файла поставить
> отметку о том, что программа поддерживает больше двух гигабайт
> памяти. Подробности в гугле.

Пишут, что это не помогает: http://www.ixbt.com/soft/windows-4gb.shtml


 
Servy ©
 
(2008-12-30 01:35)
[26]

> Пишут, что это не помогает: http://www.ixbt.com/soft/windows-
> 4gb.shtml

Вы видимо или не дочитали, или не в теме:

Время от времени можно увидеть совет по увеличению памяти, доступной системе: добавить в файл boot.ini параметр /3GB. На самом деле этот совет, как говорится, не из той оперы. Этот параметр обеспечивает перераспределение виртуального адресного пространства приложений между ними и системой, но никак не влияет на работу с физической памятью.

Вам был данный совет был дан как раз для того, чтобы вашей программе было доступна 3 Гб виртуальной памяти, а не физической. Out of memory возникает, если программе не хватает виртуальной памяти (если не хватает физической, просто начнется своппинг). В чем разница между физической и виртуальной памятью написано во многих источниках, гугл в помощь.

ЗЫ Сам писал программу, которая выкушивала 2,8 гигабайта памяти :).


 
Хост
 
(2008-12-30 01:48)
[27]


> Servy ©   (30.12.08 01:35) [26]
> (если не хватает физической, просто начнется своппинг)

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


 
Servy ©
 
(2008-12-30 03:38)
[28]

> Тогда похоже вы сами не прочитали статью.
> Там как раз о том, что никаким свопингом нельзя получить
> больше памяти.

Процитируйте, пожалуйста, где там говорится о том, что программе нельзя выделить ~3 Гб виртуальной памяти (имея меньший объем ОЗУ). Я полагаю, что такого там не написано (потому что это неправда).

Статья о том, что 32битные версии Windows не могут полноценно работать с 4 гигабайтами ОЗУ, потому как часть адресов заблокирована внешними устройствами, и система видит лишь около 3 Гб физической памяти. Какое отношение сей прискорбный факт имеет к выделяемой вашей программе виртуальной памяти остается загадкой.

Необходимость ключа /3Gb и установленного бита в PE заголовке очень проста: нижние (младшие) 2 гигабайта виртуального адресного пространства выделяются приложению для своих нужд, верхние 2 гигабайта оставляют системе. Начиная где-то с Win2000 Microsoft догадался, что 2гб пользовательским программам может быть и маловато, и заметил, что системные функции можно впихнуть и в 1 гигабайт. Однако, выделение более 2х  гигабайт виртуальной памяти приводило к краху некоторых программ — программисты привыкли, что старший бит указателя всегда равен 0, и использовали этот бит для своих нужд, что приводило к неправильной работе, если программе выделялось память с адресом выше $7FFFFFFF. Поэтому, чтобы обеспечить работоспособность таких программ, был введен указанный ключ и бит в PE заголовке, которые позволяют убедить Windows, что ваша программа не использует старший бит в указателе для своих нужд и соответственно может спокойно работать с тремя гигабайтами виртуальной памяти.

Еще раз, советую вам ознакомиться с концепцией виртуальной памяти, например, здесь:
http://ru.wikipedia.org/wiki/Виртуальная_память
и уяснить, что память, которая выделяется вами с помощью SetLength является виртуальной памятью, и адрес любой переменной или процедуры, получаемый вашей программой, является виртуальным адресом, а не адресом в физической памяти.


> [18] Jeer ©

Прошу прощения, достоверно я знал о том, что ~3 Гб памяти путем упомянутых махинаций можно выделить в WinXP и выше. Я не отрицаю тот факт, что флаг /3Gb может поддерживаться и в более ранних системах. Правда, к чему пассы в сторону PAE мне непонятно, учитывая что прикладной программе выделяется виртуальная память. Ключа /3Gb в вашем конфиге нет, а значит одно приложение не сможет выделить более примерно 2х гигабайт виртуальной памяти (разумеется, это не помешает системе воспользоваться всем доступным ей объемом ОЗУ в случае запуска более чем одного memory consuming приложения).


> [0]
> Когда массиву задаёшь слишком большие размеры, то не редко
> появляется такое сообщение. Нет ли какой-нибудь функции,
> чтобы заранее проверять есть достаточно памяти или нет?

Такой функции нет по той причине, что в большинстве случаев, если программа говорит выделить ей некоторое количество памяти, значит для ее работы _необходимо_ указанное количество памяти, и невозможность выделения означает ошибку. Случай, когда программа может обойтись и половиной указанного количества памяти достаточно редок (это подразумевает алгоритм, который может работать как если ему выделена память полностью в запрощенном объеме, так и лишь частично; такие алгоритмы встречаются нечасто).

Если вам хочеться именно определить, можно ли выделить указанное количество памяти, или нет, это сделать очень просто, о чем и написано в [1]. Если вы не знаете что такое try except, или не понимаете как он работает, к вашим услугам хелп. Написать процедуру выделения максимального доступного объема тоже не сложно, try except для отлавливания факта неудачи выделения и бинарный поиск.


 
han_malign ©
 
(2008-12-30 12:00)
[29]


> > Нет ли какой-нибудь функции, чтобы заранее проверять есть достаточно памяти или нет?

> Такой функции нет

— функция то есть, только для ее использования надо приложить некоторые усилия…
VirtualQuery
для получения карты использования виртуальной памяти надо максимум 2Гб/64Кб = 65536 итераций — поиск свободного диапазона адресов максимальной длинны вполне тривиальная задача, но не для частого использования, с возможными граблями в многопоточном варианте, и возможным крахом менеджера памяти(«DelphiMM») при резервировании этого диапазона(VirtalAlloc) …


> try except для отлавливания факта неудачи

p:=SysGetMem(sz); p <> nil
seh-офилы, блин…


 
Servy ©
 
(2008-12-30 13:10)
[30]

> > Такой функции нет
>
> — функция то есть, только для ее использования надо приложить
> некоторые усилия…

Имелось в виду:

Готовой такой функции нет, однако, ее можно написать, о чем и говорилось в следующем абзаце.


> > try except для отлавливания факта неудачи
>
> p:=SysGetMem(sz); p <> nil
> seh-офилы, блин…

*Servy сжег все книги, расхваливающие seh и посыпал голову пеплом*

А если серьезно, то могу попытаться отмазаться тем, что строке (или дин. массиву), которому автор делает SetLength нужно еще около дюжины байт для служебных данных длины, кол-ва ссылок и т.п.), причем кол-во этих даннных может отличаться в разных версиях делфи. То есть, если мы можем выделить 3000 байт памяти, это еще не означает, что мы можем установить длину некой строки в 3000. Соответственно, нужно учитывать этот запас, который от версии к версии может поменяться. Вариант с try except имеет в этом плане преимущество, хотя выполняется очевидно несколько медленнее.



Re: Увеличить память для приложения (EOutOfMemory)

От:

glh

Россия

 
Дата:  15.10.14 17:33
Оценка:

16 (2)

Здравствуйте, indee, Вы писали:

I>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).

I>Можно ли в Windows выделить больше памяти для выполнения приложения?

Ваше приложение съело всю доступную память?
На моей памяти я видел такое 2 раза, и оба, незадачливый

программист

кодер, грузил огромную таблицу в DevExpress Grid.

В порядке предпочтения осмелюсь предложить.
1) Перепишите логику работы.
2) Задействуйте другой менеджер памяти, с более подходящей для вас стратегией.
3) Переделайте для 64 разрядов.
4) http://bit.ly/ZE1d3S

К прочтению:
Архитектура памяти в Windows
Архитектура памяти в Windows (spin-off)
Адресное пространство под микроскопом

Manager Location
HeapAlloc-based memory manager http://cc.embarcadero.com/Item.aspx?id=22668
PSD Memory Manager (based on RecyclerMM ) http://dennishomepage.gugs-cats.dk/memoryManagerChallenge.htm
RecyclerMM http://glscene.sourceforge.net/RecyclerMM.htm
NexusDB http://www.nexusdb.com/
MultiMM http://cc.embarcadero.com/Item.aspx?id=14283
FastMM http://sourceforge.net/projects/fastmm/
FastSharemem http://www.thejobpage.com/emil/codexterity/fastsharemem.htm
ProcessMemMgr http://home.foni.net/~winter/delphi-bits/PrcMemMgr.zip
qmem http://www.torry.net/vcl/vcltools/debug/qmemory.zip, http://www.ussr.to/Russia/delphiplus/downloads/library/qmem.zip
HPMemMgr http://www.optimalcode.com/memmgr.htm, http://codecentral.borland.com/codecentral/snippets/14283.zip
SapMM https://code.google.com/p/sapmm/
scalemm http://code.google.com/p/scalemm/
SynScaleMM http://blog.synopse.info/post/2010/12/04/SynScaleMM
SafeMM http://cc.embarcadero.com/item/27241

PS. Претензии по ссылкам не принимаются, все были актуальны на момент сохранения.

Успехов!
C уважением, Алексей.
————————————————
Хороших %s не бывает — бывает не худший вариант.


Увеличить память для приложения (EOutOfMemory)

От:

indee

 
Дата:  15.10.14 15:59
Оценка:

Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).
Можно ли в Windows выделить больше памяти для выполнения приложения?

Спасибо!


Re: Увеличить память для приложения (EOutOfMemory)

От:

RainBoy

 
Дата:  29.10.14 20:12
Оценка:

{$SETPEFLAGS $0020} // IMAGE_FILE_LARGE_ADDRESS_AWARE = $0020;

http://cc.embarcadero.com/item/24309

В моей практике реально понадобилось 1 раз, когда сторонняя DLL кушала > 1.7 Gb памяти.

… << RSDN@Home 2.2.0 alpha 5 rev. 0>>


Re: Увеличить память для приложения (EOutOfMemory)

От:

jhfrek

Россия

 
Дата:  29.10.14 20:22
Оценка:

Здравствуйте, indee, Вы писали:

I>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).

если количество объектов реально большое и они реально нужны, их надо кэшировать в собственном менеджере памяти, потому как дельфийский можно действительно переполнить за счет сегментации


Re[2]: Увеличить память для приложения (EOutOfMemory)

От:

indee

 
Дата:  30.10.14 08:48
Оценка:

Здравствуйте, jhfrek, Вы писали:

J>Здравствуйте, indee, Вы писали:


I>>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).


J>если количество объектов реально большое и они реально нужны, их надо кэшировать в собственном менеджере памяти…

Можно подробнее?
Спасибо!


Re[3]: Увеличить память для приложения (EOutOfMemory)

От:

Danchik

Украина

 
Дата:  30.10.14 10:39
Оценка:

Здравствуйте, indee, Вы писали:

I>Здравствуйте, jhfrek, Вы писали:


J>>Здравствуйте, indee, Вы писали:


I>>>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).


J>>если количество объектов реально большое и они реально нужны, их надо кэшировать в собственном менеджере памяти…


I>Можно подробнее?

I>Спасибо!

Попробуйте менеджеры памяти котрые вам описывали выше. Еще рано писать свой.


Re[3]: Увеличить память для приложения (EOutOfMemory)

От:

glh

Россия

 
Дата:  30.10.14 16:21
Оценка:

Здравствуйте, indee, Вы писали:

I>Можно подробнее?

Я бы все же начал с ответа на вопросы:
Почему? (создается так много объектов)
Зачем? (они все нужны, прямо сейчас, одновременно)

Не зря предложение изменить логику работы идет первым.

Это самый интенсивный способ.
Остальные или отодвигают проблему на потом или решают ее количественно.

Игровые миры содержат огромное количество объектов-полигонов. Однако работают.
Текстовые редакторы редактируют огромные тексты пользуясь небольшим буфером.
Во времена DOS, а там существенные ограничения на память были, 16 бит все-таки, обрабатывали массивы данных ну никак не помещавшиеся в ОЗУ, вытесняли не используемые страницы на диск.

Успехов!
C уважением, Алексей.
————————————————
Хороших %s не бывает — бывает не худший вариант.


Re[3]: Увеличить память для приложения (EOutOfMemory)

От:

jhfrek

Россия

 
Дата:  30.10.14 20:13
Оценка:

Здравствуйте, indee, Вы писали:

J>>если количество объектов реально большое и они реально нужны, их надо кэшировать в собственном менеджере памяти…

I>Можно подробнее?

к примеру

код где цепочка циклов символизирует глубокую вложенность процедуры где очень много раз выделяется память

for i := 1 to 10000000 do
  for j := 1 to 1000000 do
    ...
      for k := 0 ro 100000 do begin
        getmem(sizeof(integer))
        ....
        freemem()
      end

меняем на array of pointer := getmem(sizeof(integer) * большое число), а вместо getmem(), freemem() пишем inc/dec (указатель на свободное место в массиве)

ЗЫ. видел код где Assign производился через последовательность object.Free; object.CreateCopy(newObject). Банальный рефакторинг сильно уменьшил нагрузку на менеджер памяти. Так что я бы сильно поанализировал, прежде чем заниматься оптимизацией менеджера.
ЗЗЫ. Еще встречал когда динамические массивы в цикле мучили SetLength(array, Length(array) + 1)…


Re: Увеличить память для приложения (EOutOfMemory)

От:

indee

 
Дата:  16.12.14 09:25
Оценка:

Здравствуйте, indee, Вы писали:

I>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).

I>Можно ли в Windows выделить больше памяти для выполнения приложения?

I>Спасибо!

OS Windows XP, 4GB RAM, Task Manager показывает, что использовано 60% памяти, приложение съело не более 250MB и Out of memory (EOutOfMemory)…
Почему не доступна для приложения оставшаяся свободная память Windows?


Re[2]: Увеличить память для приложения (EOutOfMemory)

От:

BlackEric

http://black-eric.lj.ru
Дата:  16.12.14 14:17
Оценка:

Здравствуйте, indee, Вы писали:

I>OS Windows XP, 4GB RAM, Task Manager показывает, что использовано 60% памяти, приложение съело не более 250MB и Out of memory (EOutOfMemory)…

I>Почему не доступна для приложения оставшаяся свободная память Windows?

Возможно, ему нужен большой непрерывный кусок


Re[2]: Увеличить память для приложения (EOutOfMemory)

От:

indee

 
Дата:  17.12.14 08:17
Оценка:

Здравствуйте, glh, Вы писали:

glh>Здравствуйте, indee, Вы писали:


I>>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).

I>>Можно ли в Windows выделить больше памяти для выполнения приложения?

glh>Ваше приложение съело всю доступную память?

Я был бы рад, если приложение съест всю доступную память…


Re[3]: Увеличить память для приложения (EOutOfMemory)

От:

BlackEric

http://black-eric.lj.ru
Дата:  17.12.14 09:12
Оценка:

Здравствуйте, indee, Вы писали:

I>Здравствуйте, glh, Вы писали:


glh>>Здравствуйте, indee, Вы писали:


I>>>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).

I>>>Можно ли в Windows выделить больше памяти для выполнения приложения?

glh>>Ваше приложение съело всю доступную память?


I>Я был бы рад, если приложение съест всю доступную память…

Какой делфи и менеджер памяти?


Re[2]: Увеличить память для приложения (EOutOfMemory)

От:

jhfrek

Россия

 
Дата:  17.12.14 09:16
Оценка:

Здравствуйте, indee, Вы писали:

I>OS Windows XP, 4GB RAM, Task Manager показывает, что использовано 60% памяти, приложение съело не более 250MB и Out of memory (EOutOfMemory)…

I>Почему не доступна для приложения оставшаяся свободная память Windows?

попробуйте тупо прописать fastmm и посмотрите что получится


Re[2]: Увеличить память для приложения (EOutOfMemory)

От:

Dimonka

Верблюд

 
Дата:  17.12.14 12:09
Оценка:

Здравствуйте, indee, Вы писали:

I>OS Windows XP, 4GB RAM, Task Manager показывает, что использовано 60% памяти, приложение съело не более 250MB и Out of memory (EOutOfMemory)…

250 мб — это совсем не много. Дело в чём-то другом. Попробуй создать лог создания/уничтожения и посмотри что создаётся и от чего падает.


Re[4]: Увеличить память для приложения (EOutOfMemory)

От:

indee

 
Дата:  17.12.14 12:55
Оценка:

Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, indee, Вы писали:


I>>Здравствуйте, glh, Вы писали:


glh>>>Здравствуйте, indee, Вы писали:


I>>>>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).

I>>>>Можно ли в Windows выделить больше памяти для выполнения приложения?

glh>>>Ваше приложение съело всю доступную память?


I>>Я был бы рад, если приложение съест всю доступную память…


BE>Какой делфи и менеджер памяти?

Delphi 7, менеджер памяти по умолчанию (Borland MM?)


Re[3]: Увеличить память для приложения (EOutOfMemory)

От:

indee

 
Дата:  17.12.14 13:45
Оценка:

Здравствуйте, Dimonka, Вы писали:

D>Здравствуйте, indee, Вы писали:


I>>OS Windows XP, 4GB RAM, Task Manager показывает, что использовано 60% памяти, приложение съело не более 250MB и Out of memory (EOutOfMemory)…


D>250 мб — это совсем не много. Дело в чём-то другом. Попробуй создать лог создания/уничтожения и посмотри что создаётся и от чего падает.

Проверял, построчно проверял утечку создания/уничтожения — все не очень плохо.
Плохо то, что я не могу создать большое кол-во «жирных» обjектов.

Зачем покупать 4Gb на WinXP32, если при 1Gb все так же валится, не зависимо от объема свободной памяти.


Re[5]: Увеличить память для приложения (EOutOfMemory)

От:

BlackEric

http://black-eric.lj.ru
Дата:  17.12.14 14:34
Оценка:

Здравствуйте, indee, Вы писали:

BE>>Какой делфи и менеджер памяти?


I>Delphi 7, менеджер памяти по умолчанию (Borland MM?)

Ему нужна непрерывная память для выделения. Попробуйте использовать FastMM.
Или выделяйте при старте память с запасом, а потом работайте с этим участком


Re[4]: Увеличить память для приложения (EOutOfMemory)

От:

Dimonka

Верблюд

 
Дата:  17.12.14 15:03
Оценка:

Здравствуйте, indee, Вы писали:

I>Проверял, построчно проверял утечку создания/уничтожения — все не очень плохо.

I>Плохо то, что я не могу создать большое кол-во «жирных» обjектов.

Может тогда скажешь что за обьекты? Может другие идеи появятся как помочь?
«Жирные обьекты» можно разбивать на несколько менее жирных, либо проецировать в memory mapped files.


Re[6]: Увеличить память для приложения (EOutOfMemory)

От:

indee

 
Дата:  03.01.15 08:49
Оценка:

Здравствуйте, BlackEric, Вы писали:

BE>Здравствуйте, indee, Вы писали:


BE>>>Какой делфи и менеджер памяти?


I>>Delphi 7, менеджер памяти по умолчанию (Borland MM?)


BE>Ему нужна непрерывная память для выделения. Попробуйте использовать FastMM.

BE>Или выделяйте при старте память с запасом, а потом работайте с этим участком

Спасибо за совет!

С FastMM все работает гараздо лучше, там где приложение ело 200Мб, сейчас всего 8Мб.


Re[7]: Увеличить память для приложения (EOutOfMemory)

От:

vladislav_somov

Россия

 
Дата:  25.01.15 21:26
Оценка:

Здравствуйте, indee, Вы писали:

I>Здравствуйте, BlackEric, Вы писали:


BE>>Здравствуйте, indee, Вы писали:


BE>>>>Какой делфи и менеджер памяти?


I>>>Delphi 7, менеджер памяти по умолчанию (Borland MM?)


BE>>Ему нужна непрерывная память для выделения. Попробуйте использовать FastMM.

BE>>Или выделяйте при старте память с запасом, а потом работайте с этим участком

I>Спасибо за совет!


I>С FastMM все работает гараздо лучше, там где приложение ело 200Мб, сейчас всего 8Мб.

Я бы все же посоветовал взглянуть на архитектуру под другим углом. FastMM, в данном случае, — это «лечение симптомов», а не решение проблемы. Если при этом Вы не самостоятельно работаете активно с памятью, то, возможно, работаете, например, со стоками или с классом TStringList (возможно, неявно).


Re[2]: Увеличить память для приложения (EOutOfMemory)

От:

vladislav_somov

Россия

 
Дата:  20.02.15 20:40
Оценка:

Здравствуйте, indee, Вы писали:

I>Здравствуйте, indee, Вы писали:


I>>Программа (написанная на Delphi) создает большое количество объектов. Иногда это приводит к Out of memory (EOutOfMemory).

I>>Можно ли в Windows выделить больше памяти для выполнения приложения?

I>>Спасибо!


I>OS Windows XP, 4GB RAM, Task Manager показывает, что использовано 60% памяти, приложение съело не более 250MB и Out of memory (EOutOfMemory)…

I>Почему не доступна для приложения оставшаяся свободная память Windows?

Фрагментация памяти. FastMM спасет, но лучше все же разобраться с болезнью, а не с симптомами.

Подождите ...

Wait...

  • Переместить
  • Удалить
  • Выделить ветку

Пока на собственное сообщение не было ответов, его можно удалить.

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,
Anne

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

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:

  • Tek-Tips ForumsTalk 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

Перейти к содержимому

Сообщение «Out of memory» в Delphi при работе с динамическими массивами скорее всего возникает при больших объёмах массивов и использовании функции SetLength в виде: SetLength(массив, Length(массив) + 1). Память пошагово, паленькими порциями, выделяемая под массив, оказывается «разорвана на куски», чем если бы ей выделяли сразу достаточно большой кусок. Выход простой: выделяем, как и положено, заранее просчитав необходимый объём, не x+1, а сразу достаточное количество памяти для решения типичной задачи. Если же памяти надо ещё больше — добавляем очередной большой кусок. Для контроля последней записи используем переменную.

Есть база данных на SQLite, подключение в проект через FireDAC, компоненты TFDManager, TFDConnection, TFDQuery.
Одна процедура динамически создает 4 таблицы и заполняет данными. На этом этапе все хорошо, объем памяти программы увеличивается на 10 — 12 Мб. Другая процедура многократными запросами к эти четырем таблицам заполняет данными другие 8 таблиц. Здесь начинает расти количество памяти, занимаемой приложением, и в итоге доходит до 2Гб и ошибка out of memory. Пробовал удалять и создавать TFDConnection и TFDQuery под каждый блок данных, но ничего не помогает. На сегодня код такой:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
      BasebcConnectionSQL.Connected := false;
      BasebcConnectionSQL.Free;
      BasebcConnectionSQL:= TFDConnection.Create(Self);
      BasebcConnectionSQL.DriverName:= 'SQLite';
      BasebcConnectionSQL.Params.Database :=  PutiMyBaseSQL;
      BasebcConnectionSQL.Connected := true;
      BasebcConnectionSQL.Open();
      FDQ := TFDQuery.Create(Self);
      FDQ.Connection := BasebcConnectionSQL;
...
      FDQ.SQL.Text := 'Select *...';
      FDQ.Open;
...
      FDQ.Free;

расчеты и данные в таблицах без ошибок (перепроверено вручную), но данные не удаляются а накапливаются.
Может кто знает как удалять ненужные данные из памяти приложения?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

Go Up to Using ILINK32 and ILINK64 on the Command Line

When using the RAD Studio ILINK32 or ILINK64, you may receive the Fatal: Out of memory message. To handle it, you need to identify the Linker heap that is out of memory and increase its size.

To increase the memory size in the needed heap, do the following:

1. Go to Tools > Options > IDE > Compiling and Running.
2. To see which Linker heap caused the problem, select Diagnostic on the Verbosity menu.
3. Try to link again, and when you see the Fatal: Out of memory message, click the Output tab. It contains additional information that identifies which Linker heap was overrun.
4. On the Output tab, find the following line:

Overrun on linker heap:
The heap that you see after the Overrun on linker heap: message is the heap that was overrun.
Values for all heaps are listed below this line. Please see the example below.

  • Look at the two hex values following the heap that is overrun.
  • The first value shows the size required by the linker when it realized that the heap would be overrun.
  • The second value shows the allocated size.
  • Compare the first and second values and pick a value for the heap that exceeds the first value.

Handling errors.png
5. Now, you can increase the size of the needed heap. To do it, go to Project > Options > C++ Linker and in the Linker Heap Settings section, set the new heap size.

  • For the 32-bit Windows platform, there are 5 heaps. In most cases, it’s enough to increase 3 of them: Code Heap Size, Data Heap Size, or Info Heap Size. Please see the sample values used in a reported test case:
  • Code Heap Size: 0x14000000
  • Data Heap Size: 0x0d000000
  • Info Heap Size: 0x0B000000
  • RO Data Heap Size: 0
  • TDS Heap Size: 0
  • For the 64-bit Windows platform, there are 14 heaps. In most cases, it’s enough to increase 2 of them: Dwarf pubtypes Heap Size, or Dwarf aranges Heap Size. Please see the sample values used in a reported test case:
  • Code Heap Size: 0
  • Data Heap Size: 0
  • Dwarf abrbrev Heap Size: 0
  • Dwarf aranges Heap Size: 0
  • Dwarf info Heap Size: 0
  • Dwarf line Heap Size: 0
  • Dwarf loc Heap Size: 0
  • Dwarf macinfo Heap Size: 0
  • Dwarf pubtypes Heap Size: 0x02400000
  • Dwarf ranges Heap Size: 0
  • Dwarf str Heap Size: 0x08000000
  • Info Heap Size: 0
  • RO Data Heap Size: 0
  • TDS Heap Size: 0
C++Linker.png

6. Try to link again. In case you see the Fatal: Out of memory message again, repeat the procedure because you might need to increase the memory for other heaps too.

Note: Each application requires increasing different heaps and different values.

Command-Line Flags

In a command-line build, the linker will emit a table like the following example:

Turbo Incremental Link64 6.80 Copyright (c) 1997-2017 Embarcadero Technologies,
Inc.
Overrun on linker heap: info
Linker Heaps
------------
info                   0x12271000  0x12000000
code                   0x0487d000  0x08000000
rodata                 0x00159000  0x06000000
data                   0x029bb000  0x08000000
bss                    0x08000000  0x08000000
dwarf_aranges          0x00010000  0x00200000
dwarf_macinfo          0x00010000  0x00200000
dwarf_pubtypes         0x00275000  0x02000000
dwarf_info             0x04e57000  0x06000000
dwarf_abbrev           0x00040000  0x00200000
dwarf_line             0x0124d000  0x02000000
dwarf_str              0x036e0000  0x06000000
dwarf_loc              0x00070000  0x02000000
dwarf_ranges           0x00275000  0x02000000
Fatal: Out of memory

You can change the heap sizes the linker uses via the -GH flag for ilink32 or ilink64. Use -GH<heapname>=size to allocate a larger heap or multiple heaps. For example, to link the release version of the DLL OWLNext library, internal C++Builder developers use -GHinfo=0x13000000.

See Also

  • Using ILINK32 and ILINK64 on the Command Line
  • Technical Details About ILINK32 and ILINK64
  • C++ Linker

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,
Anne

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

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:

  • Tek-Tips ForumsTalk 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

Добрый день, уважаемые пользователи.
Суть проблемы: При запуске процедуры идет работа в файле размеров в …. мегабайт. И после 5 секунд выскакивает окно out of memory. Хотя файлы до 200 мегабайт нормально.
procedure Tfrm_Main.Run;
var afList: TStringDynArray;
i, j, k: integer;
L, rL, fL: TStringList;
NewName, tmp: String;
begin
memo_Log.Lines.Add(Format(‘Начало обработки: %s’, [DateTimeToStr(Now)]));
memo_Log.Lines.Add(‘///’);
memo_Log.Lines.Add(»);
L := TStringList.Create;
for i := 0 to memo_Folders.Lines.Count — 1 do
begin
afList := TDirectory.GetFiles(memo_Folders.Lines[i], ‘*.txt’, SO);
for j := 0 to Length(afList) — 1 do
L.Add(afList[j]);
end;
rL := TStringList.Create;
rL.Text := Trim(memo_List.Text);
k := 0;
fL := TStringList.Create;
for i := 0 to L.Count — 1 do
begin
memo_Log.Lines.Add(Format(‘Обработка файлов %s’, [L.Strings[i]]));
fL.LoadFromFile(L.Strings[i]);
tmp := ExtractFileName(L.Strings[i]);
tmp := Copy(tmp, 1, Pos(‘.’, tmp) — 1);
NewName := Format(‘%s%s.%s’, [ExtractFilePath(L.Strings[i]),
tmp,
FormatDateTime(‘ddmmyy_hhnn’, Now)]);
if rg_Order.ItemIndex = 1 then
for j := 0 to rL.Count — 1 do
rL.Exchange(j, RandomRange(0, rL.Count));
for j := 0 to fL.Count — 1 do
begin
fL.Strings[j] := StringReplace(fL.Strings[j], edt_Word.Text, rL.Strings[k], RF);
inc(k);
if k = rL.Count then k := 0;
end;
fL.SaveToFile(NewName);
memo_Log.Lines.Add(Format(‘Сохранение под именем %s’, [NewName]));
memo_Log.Lines.Add(»);
end;
memo_Log.Lines.Add(‘///’);
memo_Log.Lines.Add(Format(‘Окончание обработки: %s’, [DateTimeToStr(Now)]));
fL.Free;
rL.Free;
L.Free;
btn_Next.Enabled := false;
LoadBMP(btn_Prev, 5);
btn_Prev.Caption := ‘С начала’;
end;

Ответ

Это не утечка. TStringList имеет ограничение на работу с очень большими файлами (учитывая, что размер файла в памяти после загрузки увеличится вдвое). Как раз 5-10 секунд проходит до того момента, как он упирается в него.
Используйте либо классический readln, либо перерабатывайте под себя TFileStream. Вот пример, давно использованный в нашей программе для работы с большими текстами, переработайте его под себя:
type
TTextFileStream = class(TFileStream)
private
FBuffer: string;
public
function Eof: Boolean;
procedure WriteLn(Text: string);
function ReadLn: string;
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
function RowsCount: Integer;
end;
implementation
{ TTextFileStream }
function TTextFileStream.Eof: Boolean;
begin
Eof := ((Position — Length(FBuffer)) = Size);
end;
function TTextFileStream.ReadLn: string;
const
BufferLength = 10000;
var
NewBuffer: string;
Readed: Integer;
begin
Readed := 1;
while (Pos(#13, FBuffer) = 0) and (Readed > 0) do begin
SetLength(NewBuffer, BufferLength + 2);
Readed := Read(NewBuffer[1], BufferLength);
SetLength(NewBuffer, Readed);
FBuffer := FBuffer + NewBuffer;
end;
if Pos(#13, FBuffer) > 0 then begin
Result := Copy(FBuffer, 1, Pos(#13, FBuffer) — 1);
Delete(FBuffer, 1, Pos(#13, FBuffer) + 1);
end else begin
Result := FBuffer;
FBuffer := »;
end;
end;
function TTextFileStream.RowsCount: Integer;
begin
Result := 1;
FBuffer := »;
Seek(0, soBeginning);
while not Eof do begin
ReadLn;
Inc(Result);
end;
Seek(0, soBeginning);
end;
function TTextFileStream.Seek(const Offset: Int64;
Origin: TSeekOrigin): Int64;
begin
if Origin = soCurrent then
Result := inherited Seek(Offset — Length(FBuffer), Origin)
else Result := inherited Seek(Offset, Origin);
FBuffer := »;
end;
procedure TTextFileStream.WriteLn(Text: string);
const
NewLine = #13#10;
begin
Seek(0, soCurrent);
Write(Text[1], Length(Text));
Write(NewLine, 2);
end;

FILE_FLAG_NO_BUFFERING places special requirements on use of the file handle, that are not compatible with all functionality of Delphi’s THandleStream class. The principal such requirement is that all access is aligned. By which it is meant that the file pointer is always placced on sector boundaries, and all reads and writes are of multiples of the sector size. The specific failure point here is the Size property.

You are reading a file whose size is not an exact multiple of the sector size. The answer you refer to fails with the error you report when presented a file whose size is not an exact multiple of the sector size. Presumably the author of that code was not aware of the issue and by pure chance used a file whose size was an exact multiple of the sector size.

You can confirm all of this by executing the code with an input file whose size is an exact multiple of 4096.

You likely can use THandleStream with such a file handle but you will need to be careful. Obviously you must avoid Size. You have to respect the alignment requirements. You need to be careful when reading at the end of the file because you will need to read an entire sector even if you know that the logical file ends before the end of the sector. That means using Read rather than ReadBuffer.

Frankly, in my opinion, if you must use unbuffered file access then I don’t believe that the stream abstraction is a good fit. I would work directly with the Windows API.

FILE_FLAG_NO_BUFFERING places special requirements on use of the file handle, that are not compatible with all functionality of Delphi’s THandleStream class. The principal such requirement is that all access is aligned. By which it is meant that the file pointer is always placced on sector boundaries, and all reads and writes are of multiples of the sector size. The specific failure point here is the Size property.

You are reading a file whose size is not an exact multiple of the sector size. The answer you refer to fails with the error you report when presented a file whose size is not an exact multiple of the sector size. Presumably the author of that code was not aware of the issue and by pure chance used a file whose size was an exact multiple of the sector size.

You can confirm all of this by executing the code with an input file whose size is an exact multiple of 4096.

You likely can use THandleStream with such a file handle but you will need to be careful. Obviously you must avoid Size. You have to respect the alignment requirements. You need to be careful when reading at the end of the file because you will need to read an entire sector even if you know that the logical file ends before the end of the sector. That means using Read rather than ReadBuffer.

Frankly, in my opinion, if you must use unbuffered file access then I don’t believe that the stream abstraction is a good fit. I would work directly with the Windows API.

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

Понравилась статья? Поделить с друзьями:
  • Out of memory донт старв тугезер ошибка
  • Out of memory error java lang outofmemoryerror ошибка
  • Oursson индукционная плита ошибка e0
  • Outlook ошибка 0x80190194
  • Outlook ошибка 0x800ccc80