Текущий архив: 2002.03.28;
Скачать: CL | DM;
ВнизДинамические массивы в Дельфи Найти похожие ветки
← →
Vladimir1 (2002-03-09 20:27) [0]Необходимо зачитать текстовый файл большого объема (до 6 Мб.) в массив (для сортировки строк), но Дельфи не дает создать массив соответствующего размера, даже динамический. Может кто знает, как лучше создавать динамические массивы в этом случае?
← →
Anatoly Podgoretsky (2002-03-09 20:37) [1]Дельфи позволяет создавать стуктруры данных до 2 гб, все динамические массивы создаются с помощью прцедуры SetLength
← →
Vladimir1 (2002-03-09 20:58) [2]Ругается Дельфи, но если в Setlength установить несколько десятков тысяч, то все нормально работает. Мне хотя бы пример реально работающей конструкции на большое количество элементов массива.
← →
Anatoly Podgoretsky (2002-03-09 21:12) [3]Как ругаетс, видимо секрет.
← →
drpass (2002-03-09 23:17) [4]Наверное, он пишет array of string размером несколько сотен тысяч строк. Я, конечно, так не извращался, но сомневаюсь в возможностях менеджера памяти Delphi, да и любого другого компилятора.
Может, попробовать TStringList?
← →
Anatoly Podgoretsky (2002-03-09 23:21) [5]Это потребует еще больше памяти, а сто тысяц строк скажкм при длине 80 байт ничтожно малая величина, я спокойно обрабатывал свыше миллиона и не по 80 символов. У нег явно что то другое, вот только говорить не хочет, ну это его дело, видимо сам решит.
← →
lipskiy (2002-03-10 00:07) [6]Я немного не в тему, хотя кто его знает...
Был у меня случай, когда я текстовый файл читал в динамический массив. Строк около 100 тыс, длиной разной, в среднем символов 200. Так вот, поскольку числа строк заранее не известно (а посчитать их перед заполением массива сразу в голову не пришло), то я при прочтении новой строки делал в цикле SetLength(ar,Length(ar)+1) и вносил новую строчку. При такой операции где-то на 60-ти тысячах строк выдавалась не помню какая ошибка (давно было), но что-то про недостаток ресурсов. Долго репу чесал, так как памяти физической полно было, ну и для проверки решил сразу оттяпать кусок на 200 тыс. строк, заполнить его а лишнее потом отрубить. И прошло, как ни странно! Я и больше оттяпывал - проходило! А вот построчно наращивать, то есть поэлементно (для массива) - затыкается... Природа этого явления мне самому не очень ясна. Если кто знает - почему так, мне было бы интересно послушать. М.б. и у Vladimir1 проблема в этом.
← →
drpass (2002-03-10 00:47) [7]Вероятно, дело в фрагментации памяти - при большом количестве выделений постепенно карта распределения памяти превращается в "зебру", и менеджер рано или поздно просто не находит непрерывного фрагмента требуемой длины (можно посмотреть на это функцией GetHeapStatus). А сразу выхватить большой кусок из памяти, пока она еще не фрагментирована, удается без проблем.
← →
lipskiy (2002-03-10 01:04) [8]Я, может, плохо понимаю структуру распределения памяти, но думаю так (может, и не верно).
Изначально для программы выделяется область, затем, по мере ее прожорливости, система отводит все новые и новые участки, какие-то освобождаются, какие-то занимаются вновь. Да, получается "зебра". Но ведь в памяти сидит много программ одновременно, и все они (ну не все, но некоторые) тоже пользуются ресурсами неровно и создают ту самую зебру еще до запуска моей программы. То есть, к моменту запуска память (если ОС давно не перегружалась) уже сильно фрагментирована и вроде бы не всегда должно однозначно можно мне выделить большой непрерывный участок. Или все это совсем не так?
← →
Anatoly Podgoretsky (2002-03-10 10:04) [9]Думаю не так, каждый процесс излдирован от другого, а память виртуальная.
← →
drpass (2002-03-10 12:14) [10]Память-то виртуальная, но Windows выделяет ее из физической. Менеджер памяти Delphi, по сути, единственное, что делает - вызывает стандартные функции винды malloc и realloc. Насколько я понял из документации и исходников, выторговав единый кусок памяти у винды, менеджер затем распределяет его по запросам объектов, при необходимости расширяя страницами по 16К. Вот в нем-то и может возникнуть фрагментация
← →
Anatoly Podgoretsky (2002-03-10 12:17) [11]Бе з разницы, физическая память это промежуточное место для работы процессора
← →
drpass (2002-03-10 12:35) [12]А как тогда это объяснить?
← →
Anatoly Podgoretsky (2002-03-10 12:41) [13]Дефрагментация в рамках процесса
← →
Yuri-7 (2002-03-10 14:11) [14]Все-таки согласен с drpass - во всех отношениях лучше использовать TStringList. И загружать из файла удобно, и сортировать можно, как пожелаешь.
← →
Vladimir1 (2002-03-10 20:12) [15]Использовал String, а как ругается Дельфи, не помню, могу позже уточнить. Setlength использовал 1 раз и выделял даже больше, чем нужно (немного), так как в тестовом файле я знал, сколько там строк.
Длина каждой строки не более, чем на этой странице.
Попробую Tstringlist.
← →
Набережных С. (2002-03-10 21:33) [16]
> Vladimir1 (10.03.02 20:12)
Лучше бы показал код. 6 мегабайт немного, совсем не много.
Вот этот код нормально работает, а выделяется почти 100 мегабайт. А файл больше 7 мег.
Fs:TFileStream;
Arr:array of byte;
begin
Fs:=TFileStream.Create("C:\Program Files\Borland\CBuilder5\Lib\vcl50.csm",fmOpenRead);
try
SetLength(arr,100000000{Fs.Size+1});
try
Fs.Read(Arr[0],Fs.Size);
Memo1.Lines.Text:=PChar(Copy(Arr,$2000,300));
finally
SetLength(Arr,0);
end;
finally
Fs.Free;
end;
end;
← →
Vladimir1 (2002-03-14 15:07) [17]Вот текст:
procedure TForm1.Button1Click(Sender: TObject);
var f1,f2:textfile;
s1:array [1..500000] of string;
s:array [1..500000,1..4] of string;
{tim:array [1..1000,1..10] of tdatetime;}
i,j,k,finds,c,dur1,dur2:integer;
m:string;
timea1,timeb1,timea2,timeb2:tdatetime;
begin
assignfile(f1,"out.txt");
reset(f1);
assignfile(f2,"bbb.txt");
rewrite(f2);
i:=0;
while not eof(f1) do begin
inc(i);
readln(f1,s1[i]);
end;
for j:=1 to i do begin
finds:=pos(" 2503947",s1[j]);
if finds>0 then begin
s[j,1]:=copy(s1[j],15,8);
s[j,2]:=copy(s1[j],37,8);
s[j,3]:=copy(s1[j],50,8);
m:=s1[j];
c:=6;
if (m[63]=" ") and (m[64]<>" ") and (m[65]<>" ")
and (m[66]<>" ") and (m[67]<>" ") then c:=0;
if (m[63]=" ") and (m[64]=" ") and (m[65]<>" ")
and (m[66]<>" ") and (m[67]<>" ") then c:=1;
if (m[63]=" ") and (m[64]=" ") and (m[65]=" ")
and (m[66]<>" ") and (m[67]<>" ") then c:=2;
if (m[63]=" ") and (m[64]=" ") and (m[65]=" ")
and (m[66]=" ") and (m[67]<>" ") then c:=3;
if (m[63]=" ") and (m[64]=" ") and (m[65]=" ")
and (m[66]=" ") and (m[67]=" ") then c:=4;
if c=4 then s[j,4]:=copy(s[j],68,1);
if c=3 then s[j,4]:=copy(s1[j],67,2);
if c=2 then s[j,4]:=copy(s1[j],66,3);
if c=1 then s[j,4]:=copy(s1[j],65,4);
if c=0 then s[j,4]:=copy(s1[j],64,5);
end;
end;
for j:=1 to i do begin
timea1:=strtodatetime(s[j,2]+" "+s[j,3]);
dur1:=strtoint(s[j,4]);
timeb1:=timea1+dur1/86400;
if j+1<=i then begin
timea2:=strtodatetime(s[j+1,2]+" "+s[j+1,3]);
dur2:=strtoint(s[j+1,4]);
timeb2:=timea2+dur2/86400;
if timeb1>timea2 then begin
write(f2,s[j,1]);
write(f2," ");
write(f2,s[j,2]);
write(f2," ");
write(f2,s[j,3]);
write(f2," ");
write(f2,s[j,4]);
write(f2," ");
write(f2,datetimetostr(timea1));
write(f2," ");
write(f2,datetimetostr(timeb1));
write(f2," ");
write(f2,datetimetostr(timea2));
write(f2," ");
writeln(f2,datetimetostr(timeb2));
end;
end;
end;
closefile(f1);
closefile(f2);
end;
Это с обычными массивами, с динамическими - аналогично ругается.
← →
Набережных С. (2002-03-14 17:54) [18]М-да...
Вариантов несколько:
1. Увеличить стек мег до десяти.
2. Объявить массивы глобально :(
3. Выделять динамически. Например, так:
var
s1:array of string;
s:array of array of string;
....
SetLength(S1,500000);
SetLength(s,4);
SetLength(s[0],500000);
SetLength(s[1],500000);
SetLength(s[2],500000);
SetLength(s[3],500000);
и не забыть освободить:
s1:=Copy(s1,0,0);
S[0]:=Copy(s[0],0,0);
S[1]:=Copy(s[1],0,0);
S[2]:=Copy(s[2],0,0);
S[3]:=Copy(s[3],0,0);
S:=Copy(s,0,0);
← →
Anatoly Podgoretsky (2002-03-14 21:59) [19]Набережных С. (14.03.02 17:54)
1. Увеличить стек мег до десяти.
Маловато однако, но о чем говорить, если до сих пор нет примера ругани, хотя четыре дня достаточный срок что бы уточнить.
← →
Набережных С. (2002-03-15 16:56) [20]
> Anatoly Podgoretsky © (14.03.02 21:59)
Да, думаю, на нехватку стека и ругается. А размер я на глазок прикинул: 10 млн. на массивы, остается еще 480 тысяч с мелочью - вроде должно на остальное хватить. Или я что-то упускаю?
А вообще непонятно, на кой ляд сразу весь файл в память тащить?
← →
Donal_Graeme (2002-03-15 17:14) [21]попробовал я компильнуть тот кусок кода и вот что получил :
Incompatible types в стороке
if c=4 then s[j,4]:=copy(s[j],68,1);
что, конечно же, логично :-)))
ведь ошибка и правда не была озвучена
← →
Anatoly Podgoretsky (2002-03-15 21:05) [22]SetLength(S1,500000); 2иб
SetLength(s,4);
SetLength(s[0],500000); 2иб
SetLength(s[1],500000); 2иб
SetLength(s[2],500000); 2иб
SetLength(s[3],500000); 2иб
4*500000=2000000*4 = 8 мб только на указатели для s + еще для S1 500000*4?, всего 10 иб только на указатели массива, сами строки не рассматриваю, они как бы не на стеке. Ну может остатка и хватит на все осталное, но я бы не стал так рисковать.
Donal_Graeme (15.03.02 17:14)
а чего другого ожидать, массмв то двухмерный, потому и говорю Anatoly Podgoretsky © (09.03.02 21:12).
Страницы: 1 вся ветка
Текущий архив: 2002.03.28;
Скачать: CL | DM;
Память: 0.51 MB
Время: 0.005 c