Освобождение динамического массива при EOutOfMemory
От: BJk  
Дата: 14.05.05 09:45
Оценка:
Delphi 6, WinXP
Создаю динамический двухмерный массив размер которого превышает размер доступной памяти.
Получаю ошибку о нехватке памяти, пытаюсь освободить массив, как результат память не освобождается.
Как освободить память занимаемую массивом?

Ниже приведенный код и его вариации не работают.

Секции finally и except отрабатываются.
Функции Finalize(matrix) и SetLength(matrix,0) прекрасно работают на небольших массивах, но в данном случае память не освобождается.


var
matrix: array of array of integer;

procedure CreateMatrix;
try
  SetLength(matrix,100000,100000);
finally // or except
  Finalize(matrix); // or SetLength(matrix,0);
end;
end;
Re: Освобождение динамического массива при EOutOfMemory
От: Danchik Украина  
Дата: 16.05.05 07:37
Оценка:
Здравствуйте, BJk, Вы писали:

BJk>Delphi 6, WinXP

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

BJk>Ниже приведенный код и его вариации не работают.


BJk>Секции finally и except отрабатываются.

BJk>Функции Finalize(matrix) и SetLength(matrix,0) прекрасно работают на небольших массивах, но в данном случае память не освобождается.


BJk>
BJk>var
BJk>matrix: array of array of integer;

BJk>procedure CreateMatrix;
BJk>try
BJk>  SetLength(matrix,100000,100000);
BJk>finally // or except
BJk>  Finalize(matrix); // or SetLength(matrix,0);
BJk>end;
BJk>end;
BJk>


Пойми одно: если память не выделилась — значит нечего освобождать

var
  matrix: array of array of integer;

procedure CreateMatrix;
begin
  SetLength(matrix,100000,100000); { не ставь этот код в try блок, память может не выделится и освобождать будет нечего}
  try
    { че то делай }
  except 
    SetLength(matrix,0); { мочи ее при ошибке - значит функция плохо отработала }
    raise; { ошибку наверх }
  end;
end;

1. Динамические массивы не обязательно освобождать самому. Delphi сделает это за тебя неявно. В твоем случае это будет после работы программы.
2. Старайся не использовать глобальные переменные — это плохой стиль программирования
3. Твой вариант лучше рассписать так:
type
  TMatrix : array of array of integer;

procedure CreateMatrix (Dimension1, Dimension2 : Integer) : TMatrix;
begin
  SetLength(Result, Dimension1, Dimension2);   
end;


P.S. Приблизительные подсчеты:
100000*100000*(4 {RefCount} + 4 {Size}) = ~75GB
Мой компьютер загнется
Re: Освобождение динамического массива при EOutOfMemory
От: Spaider Верблюд  
Дата: 16.05.05 07:55
Оценка:
Здравствуйте, BJk, Вы писали:

BJk>Delphi 6, WinXP

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

Памяти не хватает, т.е. она и не выделена для массива. Зачем же её освобождать?
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
--
К вашим услугам,
Re[2]: Освобождение динамического массива при EOutOfMemory
От: BJk  
Дата: 16.05.05 13:56
Оценка:
BJk>>Delphi 6, WinXP
BJk>>Создаю динамический двухмерный массив размер которого превышает размер доступной памяти.
BJk>>Получаю ошибку о нехватке памяти, пытаюсь освободить массив, как результат память не освобождается.
BJk>>Как освободить память занимаемую массивом?

Здравствуйте, Spaider, Вы писали:
S>Памяти не хватает, т.е. она и не выделена для массива. Зачем же её освобождать?

Дело в том, что при создании массива у меня начинает выделяться память, выделяется до того момента, пока не кончится (физическая+файл подкачки).
После возникновения EOutOfMemory она не освобождается! Размер свободной памяти равняется единицам мегабайт.
Освобождается только после закрытия приложения =)
Взял я это не с потолка, а из TaskManager с включенной опцией показывать Virtual Memory Size.

По мне тоже было бы логично, чтобы все работало нормально, но есть факт и я не могу ни объяснить его, ни справиться с ним.
Re[3]: Освобождение динамического массива при EOutOfMemory
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.05.05 07:13
Оценка:
Здравствуйте, BJk, Вы писали:

BJk>Дело в том, что при создании массива у меня начинает выделяться память, выделяется до того момента, пока не кончится (физическая+файл подкачки).

BJk>После возникновения EOutOfMemory она не освобождается! Размер свободной памяти равняется единицам мегабайт.
BJk>Освобождается только после закрытия приложения =)
BJk>Взял я это не с потолка, а из TaskManager с включенной опцией показывать Virtual Memory Size.
Гм. Выделение памяти в VCL — многоуровневое. Сначала VCL берет память у системы (и это видно через Taskman), а потом отдает уже тебе.
Когда ты освобождаешь память, ты возвращаешь ее VCL. И этого не видно в Taskman.
Если интересно, почитай здесь
Автор(ы): Андрей Мистик
Дата: 21.02.2003
В данной статье я постараюсь в общих чертах описать принципы работы менеджера памяти Delphi.
Зачем это нужно? Ведь, казалось бы, работает себе и работает, зачем его трогать? Это нужно по нескольким причинам. Во-первых, никогда не помешает разбор чужого кода, особенно если это грамотный код. Это возможность научиться чему-либо новому, а также получить эстетическое наслаждение. Во-вторых, никогда не лишне поглубже разобраться в чем-то, убедиться в тех вещах, в которых вы ранее не были уверены или же, наоборот, найти слабые места, о которых вы ранее и не подозревали, чтобы в будущем писать более эффективный код.
.
BJk>По мне тоже было бы логично, чтобы все работало нормально, но есть факт и я не могу ни объяснить его, ни справиться с ним.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Размер двухмерного динамического массива
От: BJk  
Дата: 17.05.05 12:43
Оценка:
Здравствуйте, Danchik, Вы писали:

D>P.S. Приблизительные подсчеты:

D> 100000*100000*(4 {RefCount} + 4 {Size}) = ~75GB
D> Мой компьютер загнется

Вы не ошибаетесь? разве не так?
var a,b,m_size: integer;
    m: array of array of smth;
begin
SetLength(m,a,b)
m_size =  a*SizeOf(Pointer) + a*b*SizeOf(smth)
end;
 

100000*100000*4 {size} + 100000*4 {RefCount} = ~37GB
Re[3]: Размер двухмерного динамического массива
От: Danchik Украина  
Дата: 17.05.05 13:40
Оценка:
Здравствуйте, BJk, Вы писали:

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


D>>P.S. Приблизительные подсчеты:

D>> 100000*100000*(4 {RefCount} + 4 {Size}) = ~75GB
D>> Мой компьютер загнется

BJk>Вы не ошибаетесь? разве не так?

BJk>
BJk>var a,b,m_size: integer;
BJk>    m: array of array of smth;
BJk>begin
BJk>SetLength(m,a,b)
BJk>m_size =  a*SizeOf(Pointer) + a*b*SizeOf(smth)
BJk>end;
 

BJk>100000*100000*4 {size} + 100000*4 {RefCount} = ~37GB
BJk>


Да ошибаюсь
Мы оба ошибаемся
Получается:

function CalcSize(Dimension1, Dimension2 : Integer; DataSize : Integer): Integer;
const
  cntEmptyArraySize = SizeOf (Integer) + SizeOf (Longint);
begin
  Result := cntEmptyArraySize +
    Dimension1 * (cntEmptyArraySize + SizeOf (Pointer) + Dimension2 * DataSize);
end;

  ShowMessage (FloatToStr (CalcSize (100000, 100000, SizeOf (Integer)) / 1024 / 1024 / 1024));


Что то около 1.25 GB
Слабо мозги варят сегодня
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.