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

Общие вопросы: версии и диалекты, синтаксис языка, cтруктуры и типы данных (массивы, строки, списки...), обработка данных и т.д.
Esgal
Сообщения: 78
Зарегистрирован: 04 ноя 2008, 01:15

28 мар 2009, 22:11

Допустим, мне дан довольно большой файл (count строк, но не больше 100000), состоящий из строк произвольной длинны (допустим до 200)

Я выделяю память под массив и под строки

Код: Выделить всё

const count=32000;
type PStr=^string;
       Arr=array[1..1] of PStr;
       PArr=^Arr;
var buf:string;
     i:1..100000;
     DArr:PArr;
begin
  ...
  {Тут было согласование файла f}
  ...
  GetMem(DArr,Count*SizeOf(PStr));
  for i:=1 to count do
  begin
    readln(f,buf);
    GetMem(DArr^[i],length(buf)+1);
    DArr^[i]^:=buf;
  end;
  ...
  {теперь я работаю с полученной структурой, и когда работа заканчивается, приходит время освобождать память}
  ...
end.
Два вопроса

1)Правильно ли я всё сделал;
2)Как теперь проще всего освободить память?
Неужели придётся заново проходить оп массиву, проверять размер каждой из строк, и выгружать каждую строку отдельно?
Luke! Use the Force! Use the Force... oh, Luke! Stop using the Force, use your head!
Аватара пользователя
Naeel Maqsudov
Сообщения: 2551
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

28 мар 2009, 23:05

1) Формально все правильно, но может быть сам подход неправильный? Вцелом задача какова?

2) Теперь место, выделенное для каждой строки придется действительно освобождать, а потом и массиы указателей.

Подумайте, может стоит отказаться от хранения string в динамическом контексте и перейти на PChar?
Esgal
Сообщения: 78
Зарегистрирован: 04 ноя 2008, 01:15

28 мар 2009, 23:49

Подумайте, может стоит отказаться от хранения string в динамическом контексте и перейти на PChar?
как это на Pchar

объясните пожалуйста если не затруднит...

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

Нужно считать строки со 2 по n+1 в память, при этом нужно занять минимальное количество памяти
--------------------------------------------------------------------------------
Добавленное сообщение
--------------------------------------------------------------------------------
я тут поэксперементировал

почемуто даже если вообще не выделять память под строки, всё перкрасно работает... т.е.

Код: Выделить всё

  GetMem(DArr,Count*SizeOf(PStr));
  for i:=1 to count do
  begin
    readln(f,buf);
    {раньше в этой строке я выделял память под строку}
    DArr^[i]^:=buf;
  end;
этот код работает... строки из массива DArr^^ прекрасно выводятся на экран, кто объяснить суть явления?
--------------------------------------------------------------------------------
Добавленное сообщение
--------------------------------------------------------------------------------
Извените за много сообщений, оказывается вышеприведённый код работает только для маленького числа строк (и всё равно непонятно почему)
Luke! Use the Force! Use the Force... oh, Luke! Stop using the Force, use your head!
Аватара пользователя
Naeel Maqsudov
Сообщения: 2551
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

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. (Когда первый байт - это длина).
atavin-ta
Сообщения: 572
Зарегистрирован: 30 янв 2009, 06:38

30 мар 2009, 11:18

&quot писал(а):)Как теперь проще всего освободить память?
Неужели придётся заново проходить оп массиву, проверять размер каждой из строк, и выгружать каждую строку отдельно?
[syntax=Delphi]
for i:=1 to count do
FreeMem(DArr^);
[/syntax]
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
BBB
Сообщения: 1272
Зарегистрирован: 27 дек 2005, 13:37

30 мар 2009, 13:01

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

30 мар 2009, 20:05

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

А есть ли вообще способ, адресовать 100 000 строк в Паскале?
--------------------------------------------------------------------------------
Добавленное сообщение
--------------------------------------------------------------------------------
atavin-ta, резвеу freemem второй параметр не обязателен?
Luke! Use the Force! Use the Force... oh, Luke! Stop using the Force, use your head!
atavin-ta
Сообщения: 572
Зарегистрирован: 30 янв 2009, 06:38

31 мар 2009, 09:39

&quot писал(а):резвеу freemem второй параметр не обязателен?
Точно не помню, но мо-моему нет.
Вопрос: "Почему вы все сионисты? Нельзя ли писать на чём то другом?".
Ответ: "Писать можно на чём угодно. Но зачем же так себя ограничивать? Пиши на С!".
Аватара пользователя
Naeel Maqsudov
Сообщения: 2551
Зарегистрирован: 20 фев 2004, 19:17
Откуда: Moscow, Russia
Контактная информация:

31 мар 2009, 15:27

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

01 апр 2009, 05:55

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