Освобождение выделанной памяти

Ответить

Код подтверждения
Введите код в точности так, как вы его видите. Регистр символов не имеет значения.

BBCode ВКЛЮЧЁН
[img] ВКЛЮЧЁН
[url] ВКЛЮЧЁН
Смайлики ОТКЛЮЧЕНЫ

Обзор темы
   

Развернуть Обзор темы: Освобождение выделанной памяти

Re: Освобождение выделанной памяти

alexander.spb » 02 апр 2009, 11:52

А действительно ли нужно считывать в RAM весь файл?
Если без этого никак -
- определите размер файла;
- выделите блок памяти этого размера;
- считайте его в RAM и обработайте как массив байтов.

Re: Освобождение выделанной памяти

somewhere » 02 апр 2009, 10:53

Во-первых, сильно сомневаюсь, что средний размер строки будет порядка 5 символов. Как бы мы не выделяли память, то общий адресуемый свободный кусок будет не более 500К, т.е. за вычетом резидентов, системных таблиц и пр. Как ни крути, но придется задействовать XMS или EMS драйвер для доступа к расширеной памяти, и осуществлять доступ к нужной строке через функцию, которая будет сама управлять подкачкой новых блоков и правкой индексов, как сказал Naeel Maqsudov.
Во-вторых, выделить память заранее для N строк, как было предложено не получится хотя бы потому, что строки имеют разную длину.
И даже создать единую таблицу поинтеров на них будет нерационально, в 64К они явно не поместятся. Однако имеет смысл хранить таблицу вида
[номер_блока_XMS]
[колво_строк_в_блоке]
А в самом блоке локальную таблицу смещений для каждой строки. Это позволит значительно ускорить обращение к нужной строке по сравнению со связаным списком, если конечно не считать времени для подкачки нужного блока из памяти (однако в связаном списке таких подкачек будет еще больше при обращении к строкам, индекс которых далеко от 0). Разумеется должна быть проверка есть ли такой блок уже подкаченный или нет.
Такая таблица кстати может кому то напомнить аппаратную связь GDT/LDT

.

BBB » 01 апр 2009, 09:24

Esgal писал(а):BBB, я тоже думал об этом...
А есть ли вообще способ, адресовать 100 000 строк в Паскале?
Списком, как уже упомянул Naeel Maqsudov.
Разве freemem второй параметр не обязателен?
В Turbo/Borland PAscal обязателен. Это в C этот параметр у аналогичной функции отсутствует.

Re: Освобождение выделанной памяти

atavin-ta » 01 апр 2009, 05:55

&quot писал(а):Если целым куском нельзя, то надо более мелкими кусками.
Связанные списки, например.
Или (если не хочется дробить данные так мелко) кусками по чуть меньше 64К, но надо будет обработать пограничные условия. Т.е. индекс элемента должен пересчитываться в номер куска и индекс элемента в куске.
Согласен, но только в том случае, когда целиком действительно нельзя или нецелесообразно. И кто сказал, что блок может быть не более 64 к? Можно использовать и 32 разряда.

Re: Освобождение выделанной памяти

Naeel Maqsudov » 31 мар 2009, 15:27

&quot писал(а):у freemem второй параметр не обязателен?
Параметр обязателен, что кажется нелогичным. Ведь кучей распоряжается все равно внутренний менеджер кучи.... Надо смотреть system.pas....
&quot писал(а):есть ли вообще способ, адресовать 100 000 строк
Если целым куском нельзя, то надо более мелкими кусками.
Связанные списки, например.
Или (если не хочется дробить данные так мелко) кусками по чуть меньше 64К, но надо будет обработать пограничные условия. Т.е. индекс элемента должен пересчитываться в номер куска и индекс элемента в куске.

Re: Освобождение выделанной памяти

atavin-ta » 31 мар 2009, 09:39

&quot писал(а):резвеу freemem второй параметр не обязателен?
Точно не помню, но мо-моему нет.

Re: Освобождение выделанной памяти

Esgal » 30 мар 2009, 20:05

BBB, я тоже думал об этом...

А есть ли вообще способ, адресовать 100 000 строк в Паскале?
--------------------------------------------------------------------------------
Добавленное сообщение
--------------------------------------------------------------------------------
atavin-ta, резвеу freemem второй параметр не обязателен?

Re: Освобождение выделанной памяти

BBB » 30 мар 2009, 13:01

К слову, если писать на Паскале, то оператор:
GetMem(DArr,Count*SizeOf(PStr));
не прокатит при (Count >= 16384). Т.е. SizeOf(PStr) = 4, а не в 32-битных приложениях нельзя выделить кусок памяти, превышающий размером 64 К.
Не скаже, что именно произойдет в данном случае: или произведение (Count*SizeOf(PStr)) по переполнению даст небольшой результат, и память выделится, но явно меньшего размера, или GetMem даст ошибку. Вообще, надо смотреть тип параметра GetMem. Если это word, то явно должно произойти переполнение его значения.

Re: Освобождение выделанной памяти

atavin-ta » 30 мар 2009, 11:18

&quot писал(а):)Как теперь проще всего освободить память?
Неужели придётся заново проходить оп массиву, проверять размер каждой из строк, и выгружать каждую строку отдельно?
[syntax=Delphi]
for i:=1 to count do
FreeMem(DArr^);
[/syntax]

Re: Освобождение выделанной памяти

Naeel Maqsudov » 29 мар 2009, 10:50

То что этот код работает это просто счастливая случайность. Так как DArr^ - это случайное число. Если его расмотреть как указатель, то оно указывает на случайное место в памяти (а не на место, которое было специально выделено).
Следовательно, DArr^^:=buf; затирает какие-то данные где-то в памяти.
Т.е. даже если это работет, это грубейшая ошибка.

&quot писал(а):как это на Pchar


На какой версии Pascal вы пишете? Начиная с 7 есть специальные функции, для работы с ASCIIZ (null-terminated) строками. Они сами обеспечивают уборку мусора. И есть стандартный тип PChar - указатель на ASCIIZ-строку.

Если используется Pascal 5, то обратите внимание на стандартные процедуры
Mark(p) и Release(p)
Запомнив состояние "кучи" по Mark можно одной командой Repease привести ее в исходное сотояние, освободив всё, что выделялось.

&quot писал(а):задача:
файл состоит из n+1 строк
в первой строке файла число n (1<=n<=100000)
В n следующих срок, строки произвольной длинны
Нужно считать строки со 2 по n+1 в память, при этом нужно занять минимальное количество памяти


Ну размер файла Вы знаете (можете определить), не так ли?
Выделите память одним куском. Считайте весь файл целиком, не тратя память на указатели и фрагментирование памяти.

Дальше можно превратить этот текст как в набор строк, идущих подряд.
Если заменить переводы строк нулями, то получатся ASCIIZ строки.
Если вставить перед каждой строки ее длину, то LASCII, соответствующие паскалевскому String. (Когда первый байт - это длина).

Вернуться к началу