Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2002.03.28;
Скачать: [xml.tar.bz2];

Вниз

Динамические массивы в Дельфи   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.007 c
4-91131
ihacker
2002-01-20 17:39
2002.03.28
пиктограмма на панели задач


3-90787
Вадим Андреевич
2002-03-04 08:36
2002.03.28
DBTable_lock record


3-90744
Sava
2002-02-28 10:52
2002.03.28
Ошибка в SQL запросе?!


1-90878
JustMan
2002-03-17 15:20
2002.03.28
Как узнать в какой папке находится Windows?


14-91054
Georg
2002-02-13 18:50
2002.03.28
Проголосуйте за наших фигуристов!!!





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский