Ошибка out of memory while expanding memory stream

I am attempting to download a file from a web server using the standard TIdHTTP and TIdSSLIOHandler components in Delphi 10.4:

memorystream := TMemoryStream.Create;
http.request.useragent:='Mozilla/5.0 (Windows NT 5.1; rv:2.0b8) Gecko/20100101 Firefox/4.0b8';
http.HandleRedirects := True;
try
  http.get('https://dl.nmkd.de/ai/clip/coco/coco.ckpt',memorystream);
except
  on E:Exception do memo.lines.add(E.Message);
  memo.lines.add(http.responsetext);
end;
application.ProcessMessages;
memorystream.SaveToFile('coco.ckpt');
memorystream.free;

The responses I get in the memo are:

Out of memory while expanding memory stream
HTTP/1.1 200 OK

The file is around 9 GB in size.

How do I get a MemoryStream to be able to handle that size? I have more than enough physical RAM installed in the PC.

Remy Lebeau's user avatar

Remy Lebeau

550k31 gold badges451 silver badges764 bronze badges

asked Jun 13, 2021 at 17:57

Some1Else's user avatar

3

Instead of loading the resource to memory temporarily, directly load it to the local file using a TFileStream:

Stream := TFileStream.Create('coco.cpkt');
try
  try
    http.get('https://dl.nmkd.de/ai/clip/coco/coco.ckpt', Stream);
  except
    on E:Exception do memo.lines.add(E.Message);
  end;
finally
  Stream.Free;
end;

answered Jun 13, 2021 at 19:01

mjn's user avatar

mjnmjn

36.4k28 gold badges175 silver badges378 bronze badges

 
Сергей

 
(2003-03-14 16:25)
[0]

При записи в поток TMemoryStream методом writeBufer возникает ошибка «Out of memory while expanding memory stream». Запись в поток осуществляется в цикле

For i:=1 to N do

begin

TMemoryStream.writebuffer(x,Sizeof(x));

end;

Число N равно 150-200 тыс.

Данных где-то около 40-50Мб.

Что можно сделать, чтобы ошибки не возникало. Заранее спасибо.


 
Smithson

 
(2003-03-14 16:31)
[1]

Что значит Out of memory?


 
Anatoly Podgoretsky

 
(2003-03-14 16:38)
[2]

А что значит Sizeof(x)


 
Сергей

 
(2003-03-14 16:42)
[3]

re: Что значит Out of memory?

Это типа не хватает памяти, а вообще в тексте приведен текст ошибки.


 
theodor_iv

 
(2003-03-14 16:52)
[4]

Тебе изначально зачем две копии одних и тех же данных в оперативной памяти, да еще по 50 мегабайт каждая?


 
Digitman

 
(2003-03-14 16:54)
[5]

зачем реально может понадобиться в памяти поток такого большого размера — ума не приложу


 
Сергей

 
(2003-03-14 16:55)
[6]

theodor_iv © : Данные пишутся из массива в поток, а затем записываюся в файл.


 
Anatoly Podgoretsky

 
(2003-03-14 16:56)
[7]

Ну так все таки, чего молчишь про Sizeof(x)


 
theodor_iv

 
(2003-03-14 16:57)
[8]

Я так и думал… А почему нельзя их сразу записать в TFileStream?


 
Сергей

 
(2003-03-14 16:59)
[9]

Digitman ©: Сначала данные из текстового файла пишуться в динамический массив, а далее, чтобы каждый раз не загружать эти данные из текстового файла (потому что очень долго), я хочу их записывать в своем формате, в двоичном файле. Загрузка такого файла осуществляется гораздо быстрее. Вот.


 
Anatoly Podgoretsky

 
(2003-03-14 17:01)
[10]

Пока ты не скажешь про Sizeof(x) тебе никто не сможет ответить, но есть подозрение что это много.


 
Сергей

 
(2003-03-14 17:02)
[11]

Sizeof(x) Вычисляет размер буфера для одного элемента массива, ну правильнее будет Sizeof(x[i])


 
kDenis

 
(2003-03-14 17:03)
[12]

> Сергей

Ну напиши ты просто:

TMemoryStream.writebuffer(x,Sizeof(x));

Без всяких цыклов…

> Anatoly Podgoretsky ©

> theodor_iv ©

Хватит издиватся над человеком!


 
Digitman

 
(2003-03-14 17:05)
[13]

> Сергей

ну и что ?

что мешает выполнить в цикле «прямую» цепочку :

InFileStream (текст) -> нужное преобразование фрагмента -> OutFileStream(бинарный формат)

?


 
Anatoly Podgoretsky

 
(2003-03-14 17:07)
[14]

Сергей (14.03.03 17:02)

Да не что он вычитает, а сколько возвращает в твоем случае


 
Сергей

 
(2003-03-14 17:10)
[15]

Без всяких цыклов…

Не получиться, потому, что размер динамического массива функцией sizeOF не вычисляется.


 
Anatoly Podgoretsky

 
(2003-03-14 17:10)
[16]

Сергей (14.03.03 17:02)

Да и раз ты уже изменил показания, то давай новый правильный код со всеми данными

kDenis © (14.03.03 17:03)

Я очень сожалею по поводу твоего негодования, но ничем не могу помочь, только автор вопроса может ответить о размере X удобным ему способом. Мы же в отличии от тебя не телепаты


 
theodor_iv

 
(2003-03-14 17:10)
[17]

> kDenis ©

Кто здесь издЕвается — так это ты… А мы помочь пытаемся, хотя и разными методами :)

> Сергей

Моя мысль вполне здравая — зачем записывать динамический массив из оперативной памяти в оперативную память, а потом в файл, если можно записать сразу в файл и сэкономить 50 мег оперативки?


 
Anatoly Podgoretsky

 
(2003-03-14 17:11)
[18]

theodor_iv © (14.03.03 17:10)

Если твое предположение насчет 50 иб верное, то встает вопрос, а где взять 10 терабайт


 
theodor_iv

 
(2003-03-14 17:14)
[19]

> Anatoly Podgoretsky ©

Я так понял, что под фразой

> Данных где-то около 40-50Мб.

понимался суммарный объем, а не объем одного Х.


 
Сергей

 
(2003-03-14 17:14)
[20]

Anatoly Podgoretsky © (14.03.03 17:07):

Дело в том, что я написал немного упрощенно. x[i] — динамический массив записей. Каждая запись в свою очередь содержит динамические структуры.

Ну короче у меня получается загрузка и запись данных для объемов

5-10 мБ. Когда я использую входные текстовые данные больших размеров возникает эта ошибка.


 
Сергей

 
(2003-03-14 17:15)
[21]

theodor_iv © (14.03.03 17:14): Все правильно понимаете


 
Anatoly Podgoretsky

 
(2003-03-14 17:18)
[22]

Давай правильный код и размеры, иначе не ответить, но если у тебя 10иб, то посчитай сам 200 000 * 10 000 000, то это 10 терабайт, а виндоус поддерживает жля пользователя только 2 гигабайта виртуальной памяти в одном процессе.


 
theodor_iv

 
(2003-03-14 17:23)
[23]

> Сергей (14.03.03 17:15)

> theodor_iv © (14.03.03 17:14): Все правильно понимаете

Для того, чтобы создать такой поток, операционке нужно выделить более 50 мегабайт оперативной памяти одним непрерывным блоком, что является для нее нетривиальной задачей. :)

На мой взгляд, единственный выход — писать сразу в TFileStream, можно еще в сочетании с TCompressionStream.


 
Сергей

 
(2003-03-14 17:25)
[24]

Anatoly Podgoretsky © (14.03.03 17:18): Какие 10иб, кто это сказал? привожу код.

//Сохранение полигона в файл

procedure SavePolygon(Stream : TMemoryStream;Pol: TPolygon);

var SizePol: integer;

begin

SizePol:= Length(POl);

Stream.WriteBuffer(SizePol,SizeOf(Integer));//Пишем длину

Stream.WriteBuffer(PChar(POl)^,SizePol*SizeOf(TPoints));

end;

end;

//Сохранение свойств полигона

procedure TProjection.SavePolygonProp1(Stream : TMemoryStream;Prop: TPropPolygon);

var SizePol: LongInt;

begin

SizePol:= SizeOf(Prop);

Stream.WriteBuffer(Prop,SizePol);

end;

//Сохранение слоя в файл

procedure TProjection.SaveLayer1(Stream:TMemoryStream;L: TLayer);

var amPolygon: dword; //Число полигонов в слое

i: integer;

begin

amPolygon:=length(L.DataP);

Stream.WriteBuffer(amPolygon,SizeOf(amPolyGon));

for i:=1 to amPolygon do

begin

SavePolygon1(stream,L.DataP[i-1]);

SavePolygonProp1(stream,l.PolProp[i-1]);

end;

Stream.WriteBuffer(L.names,SizeOf(L.names));

Stream.WriteBuffer(L.vis,SizeOf(L.Vis));

end;

strm.SaveToFile(SaveDialog1.FileName);


 
Anatoly Podgoretsky

 
(2003-03-14 17:37)
[25]

Абсолютно другой код, чем в 16:25

Но точно также неясно насчет размеров записываемых элементов

Говорите точно сколько вам вешать, в байтах, память все таки.

Если не знаешь точно, то поступи так,

заведи переменную X

перед каждым Stream.WriteBuffer делай

X := X + размер;

Label1.Caption := IntToStr(X);

//Label2.Caption := IntToStr(I);

Application.ProcessMessages;

И узнаешь правду, до этого убедись, что на диске со своп файлом есть по крайней мере свободных 2 гб


 
Digitman

 
(2003-03-14 17:45)
[26]

вот ты ответь на простой вопрос — нахрена (!!) писать данные в память, когда в результате они тут же пишутся строчкой strm.SaveToFile(SaveDialog1.FileName); в файл ?? безо всякой промежуточной обработки ?? почему сразу не писать в FileStream ??


 
theodor_iv

 
(2003-03-14 17:49)
[27]

> Digitman © (14.03.03 17:45)

нахрена (!!) писать данные в память

Видимо, какую-то тайную цель преследует. Я тут уже об этом четыре раза сказал, но ответа не получил.


 
Anatoly Podgoretsky

 
(2003-03-14 17:55)
[28]

А я не получил ответа о размере данных, в тоже время жалоба на нехватку оной. Но может если проведет отладку по указанному сценарию то все таки сообщит.


 
Serginio

 
(2003-03-14 20:35)
[29]

У меня при размере > 80 000*4 байт поэтому для записи больших данных создал свой стрим основанный на массиве больших блоков памяти. А вообще то проблема с реалоками во всех объектах которые используют непрерывную память (TList,TStringList..) если хочешь вышлю.


Многие пользователи ПК во время работы с какой-либо программой могут столкнуться с «вылетом» указанной программы, и появившимся сообщением «Out of memory». Возникшая проблема может иметь множество причин, начиная от банального недостатка памяти на пользовательском ПК, и заканчивая некорректной работой с памятью какой-либо программы.

  • Причины появления дисфункции
  • Как исправить ошибку «Out of memory»
  • Заключение

Ошибка out of memory

Причины появления дисфункции

Сообщение «Out of memory» (в переводе дословно «вне памяти», или «недостаточно памяти») обычно возникает при недостатке памяти на пользовательском компьютере. В частности же, в появлении данной ошибки «виновен» следующий набор факторов:

  • Недостаток памяти RAM на вашем ПК (рабочей памяти, планки которой установлены на материнской плате вашего компьютера). Если на вашем компьютере установлен всего 1 гигабайт памяти, вы будете встречаться с описываемой ошибкой довольно часто. Нормальным же ныне считается наличие на компьютере 4 гигабайт памяти и выше;
  • Недостаток места на жёстком диске.

Когда вашему компьютеру не хватает физической R.A.M. памяти, он заимствует часть места на жёстком диске, и создаёт так называемую «виртуальную память». Система временно хранит в такой виртуальной памяти ту часть данных, которая не помещается в памяти обычной. Такие данные обычно хранятся в файле «pagefile.sys», размер которого может увеличиваться или уменьшаться в зависимости от специфики работы вашей ОС. Если на диске будет недостаточно места, файл «pagefile.sys» не сможет расти, и пользователь получит рассматриваемую ошибку.

  • При одновременном запуске на ПК большого количества программ, каждая из которых бронирует часть памяти ПК под свои задачи;
  • При запуск большого количества вкладок браузера. Веб-навигаторы уровня «Firefox» или «Google Chrome» способны занимать от 500 мегабайт до 1 гигабайта памяти под свой функционал, при этом число открытых вкладок и соответствующей обслуживающей памяти может быть ограничено системой. Специалисты Майрософт называют такую проблему «the desktop heap limitation» — «ограничение кучи рабочего стола»);
  • Некорректная работа с памятью ряда программ (наиболее часто это игровые программы);
  • Не оптимальный размер файла подкачки, с которым работает система.Планка памяти и датчик

Для решения указанной проблемы рекомендую сделать следующее:

  1. Перезагрузите ваш ПК, и запустите требуемую программу вновь. Возможно, что проблема имеет случайный характер, и более повторяться не будет;
  2. Перед запуском нужной программы закройте другие ненужные программы (браузер, музыкальный или видео плеер, текстовый или графический редактор, мессенджер и так далее);
  3. Если проблема возникает во время серфинга в сети, закройте всё множество вкладок вашего браузера (при наличии), оставив лишь одну или две.Много открытых вкладок

Альтернативным вариантом решения проблемы является установка соответствующего фикса от Майкрософт. Или использование расширений или дополнений для браузера уровня «The Great Suspender» для «Google Chrome», хорошо работающего с ненужными вкладками браузера.

  • Добавьте оперативной памяти на ваш ПК. Если у вас на компьютере установлено 1-2 гигабайта памяти, будет оптимальным довести её объём до 4 гигабайт (а для 64-битных Виндовс 7, 8 и 10 версии рекомендую 8 и более гигабайт);Планка памяти
  • Убедитесь, что на вашем жёстком диске (или SSD) достаточно свободного места. При необходимости, освободите диск от ненужных файлов;
  • Используйте инструмент командной строки BCDEdit для изменения параметров загрузки системы. Если у вас на ПК установлена Виндовс 7 и более, запустите командную строку от имени администратора на Виндовс 7 и Виндовс 10, и в ней наберите:

bcdedit/set IncreaseUserVa 3072

И нажмите на ввод, и перезагрузите ваш ПК. Функционал данной команды позволяет выделить пользовательским приложениям 3 гигабайта оперативной памяти для работы. В некоторых системах этого может быть слишком много, потому если после ввода данной команды система начала чаще сбоить, то введите в командной строке от имени администратора:

bcdedit /set IncreaseUserVa 2560 что позволит задействовать 2,5 гигабайта вместо ранее забронированных 3.

Если ситуацию этим исправить не удалось, верните настройки на состояние по умолчанию:

bcdedit /deletevalue IncreaseUserVa

  • Увеличьте объём файла подкачки. Нажмите кнопку «Пуск», в строке поиска введите sysdm.cpl и нажмите ввод. В открывшемся окне настроек системы выберите «Дополнительно» — «Быстродействие» — «Параметры» — «Дополнительно» — «Виртуальная память» — «Изменить». Снимите галочку с опции автоматического размера, поставьте галочку на «Указать размер», и поставьте исходный размер в 8192, и максимальный в 8192. Затем выберите «Задать»;

    Окно виртуальной памяти

    Установите нужный размер файла подкачки

  • Если ошибка возникает при использовании игровой программы, перейдите в её графические настройки, и выберите их минимальные значения;
  • Произведите правильную настройку «Java». Для решения проблем с игровой программой «Майнкрафт» перейдите в Панель управления Виндовс, найдите там «Java» и запустите данную среду исполнения. Нажмите на кнопку «View», затем дважды кликните на «Runtime Parametres». Введите туда –Xms256m – Xmx3072m (или больше). Xms – это минимальное выделение ОЗУ, Xmx – максимальное. Значение Xmx рекомендуют устанавливать на процентов 70-80% от общего объёма ОЗУ. Примените изменения, и перезагрузите ваш ПК.

Заключение

Ошибка «Out of memory» может иметь множество причин, связанных как с физическим недостатком памяти на ПК, так и другими детерминантами, изложенными мной выше. Для решения проблемы советую закрыть ненужные программы (вкладки браузера) на вашем компьютере (тем самым разгрузив его память), а самым эффективным инструментом является установка дополнительной планки памяти на ПК, что в большинстве случаев поможет избавиться от ошибки на вашем компьютере.

Давайте взглянем в определение класса TMemoryStream в файле System.Classes.pas:

  TMemoryStream = class(TCustomMemoryStream)
  private
    FCapacity: Longint;
    procedure SetCapacity(NewCapacity: Longint);
  protected
    function Realloc(var NewCapacity: Longint): Pointer; virtual;
    property Capacity: Longint read FCapacity write SetCapacity;
  public
    destructor Destroy; override;
    procedure Clear;
    procedure LoadFromStream(Stream: TStream);
    procedure LoadFromFile(const FileName: string);
    procedure SetSize(const NewSize: Int64); override;
    procedure SetSize(NewSize: Longint); override;
    function Write(const Buffer; Count: Longint): Longint; override;
    function Write(const Buffer: TBytes; Offset, Count: Longint): Longint; override;
  end;

Сразу отмечаем, что для адресации памяти используются переменные типа longint, что, естественно, объясняет невозможность использования более 2 Гб. Более того, если взглянуть на методы Read (их два) непосредственного предка TMemoryStreamTCustomMemoryStream:

function TCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
begin
  if (FPosition >= 0) and (Count >= 0) then
  begin
    Result := FSize - FPosition;
    if Result > 0 then
    begin
      if Result > Count then Result := Count;
      Move((PByte(FMemory) + FPosition)^, Buffer, Result);
      Inc(FPosition, Result);
      Exit;
    end;
  end;
  Result := 0;
end;

function TCustomMemoryStream.Read(Buffer: TBytes; Offset, Count: Longint): Longint;
begin
  if (FPosition >= 0) and (Count >= 0) then
  begin
    Result := FSize - FPosition;
    if Result > 0 then
    begin
      if Result > Count then Result := Count;

      Move((PByte(FMemory) + FPosition)^, Buffer[Offset], Result);
      Inc(FPosition, Result);
      Exit;
    end;
  end;
  Result := 0;
end;

, то заметим, что результат может быть посчитан неправильно.

Поэтому решением было: заменить тип переменных внутри TMemoryStream на NativeInt и Int64, в том числе локальных переменных, а методы TCustomMemoryStream.Read переписать, например, так:

function TCustomMemoryStream.Read(var Buffer; Count: Longint): Longint;
var
  diff: Int64;
begin
  if (FPosition >= 0) and (Count >= 0) then
  begin
    diff := FSize - FPosition;
    if diff > 0 then
    begin
      if diff > Count then
        Result := Count
      else
        Result := diff;
      Move((PByte(FMemory) + FPosition)^, Buffer, Result);
      Inc(FPosition, Result);
      Exit;
    end;
  end;
  Result := 0;
end;

function TCustomMemoryStream.Read(Buffer: TBytes; Offset, Count: Longint): Longint;
var
  diff: Int64;
begin
  if (FPosition >= 0) and (Count >= 0) then
  begin
    diff := FSize - FPosition;
    if diff > 0 then
    begin
      if diff > Count then
      Result := Count
      else Result := diff;

      Move((PByte(FMemory) + FPosition)^, Buffer[Offset], Result);
      Inc(FPosition, Result);
      Exit;
    end;
  end;
  Result := 0;
end;

Это позволяет работать с объёмами памяти более 2 Гб (тестовый пример спокойно обработал 5-гигабайтный файл, полностью скопировав его в поток.

Для тех, кто захочет внести изменения у себя в System.Classes, напомню, что предварительно необходимо сохранить резервную копию этого файла — на всякий случай :)

Update 1

Для тех, кто по какой-то причине не хочет идти по предложенным выше вариантам, могу предложить класс TSegmentedMemoryStream — он доступен для скачивания и работает (проверено!).

I need to read files directly from drive without any system buffering. I tried this code here How to unload a file from cache? unfortunately I get error message saying «Out of memory while expanding memory stream». It happens with any file I tried. Later I’ve noticed that SrcStream.Size returns always value -1. So obviously problem is here and the question is why is this happening?

uses
  MMSystem;

function GetTimeForRead(ABuffered: boolean): single;
const
  FileToRead = // name of file with maybe 500 MByte size
var
  FlagsAndAttributes: DWORD;
  FileHandle: THandle;
  SrcStream, DestStream: TStream;
  Ticks: DWord;
begin
  if ABuffered then FlagsAndAttributes := FILE_ATTRIBUTE_NORMAL
  else FlagsAndAttributes := FILE_FLAG_NO_BUFFERING;
  FileHandle := CreateFile(FileToRead, GENERIC_READ, FILE_SHARE_READ, nil,OPEN_EXISTING, FlagsAndAttributes, 0);
 if FileHandle = INVALID_HANDLE_VALUE then 
 begin
   Result := 0.0;
   exit;
 end;

 SrcStream := THandleStream.Create(FileHandle);
 try
   DestStream := TMemoryStream.Create;
   try
   DestStream.Size := SrcStream.Size;

   Ticks := timeGetTime;
   DestStream.CopyFrom(SrcStream, SrcStream.Size);
   Result := 0.001 * (timeGetTime - Ticks);

 finally
  DestStream.Free;
 end;
  finally
    SrcStream.Free;
  end;
end;

Community's user avatar

asked Aug 12, 2016 at 12:01

Atak_Snajpera's user avatar

4

FILE_FLAG_NO_BUFFERING places special requirements on use of the file handle, that are not compatible with all functionality of Delphi’s THandleStream class. The principal such requirement is that all access is aligned. By which it is meant that the file pointer is always placced on sector boundaries, and all reads and writes are of multiples of the sector size. The specific failure point here is the Size property.

You are reading a file whose size is not an exact multiple of the sector size. The answer you refer to fails with the error you report when presented a file whose size is not an exact multiple of the sector size. Presumably the author of that code was not aware of the issue and by pure chance used a file whose size was an exact multiple of the sector size.

You can confirm all of this by executing the code with an input file whose size is an exact multiple of 4096.

You likely can use THandleStream with such a file handle but you will need to be careful. Obviously you must avoid Size. You have to respect the alignment requirements. You need to be careful when reading at the end of the file because you will need to read an entire sector even if you know that the logical file ends before the end of the sector. That means using Read rather than ReadBuffer.

Frankly, in my opinion, if you must use unbuffered file access then I don’t believe that the stream abstraction is a good fit. I would work directly with the Windows API.

answered Aug 12, 2016 at 12:43

David Heffernan's user avatar

David HeffernanDavid Heffernan

600k42 gold badges1065 silver badges1483 bronze badges

 
Сергей
 
(2003-03-14 16:25)
[0]

При записи в поток TMemoryStream методом writeBufer возникает ошибка «Out of memory while expanding memory stream». Запись в поток осуществляется в цикле

For i:=1 to N do

begin

TMemoryStream.writebuffer(x,Sizeof(x));

end;

Число N равно 150-200 тыс.

Данных где-то около 40-50Мб.

Что можно сделать, чтобы ошибки не возникало. Заранее спасибо.


 
Smithson
 
(2003-03-14 16:31)
[1]

Что значит Out of memory?


 
Anatoly Podgoretsky
 
(2003-03-14 16:38)
[2]

А что значит Sizeof(x)


 
Сергей
 
(2003-03-14 16:42)
[3]

re: Что значит Out of memory?

Это типа не хватает памяти, а вообще в тексте приведен текст ошибки.


 
theodor_iv
 
(2003-03-14 16:52)
[4]

Тебе изначально зачем две копии одних и тех же данных в оперативной памяти, да еще по 50 мегабайт каждая?


 
Digitman
 
(2003-03-14 16:54)
[5]

зачем реально может понадобиться в памяти поток такого большого размера — ума не приложу


 
Сергей
 
(2003-03-14 16:55)
[6]

theodor_iv © : Данные пишутся из массива в поток, а затем записываюся в файл.


 
Anatoly Podgoretsky
 
(2003-03-14 16:56)
[7]

Ну так все таки, чего молчишь про Sizeof(x)


 
theodor_iv
 
(2003-03-14 16:57)
[8]

Я так и думал… А почему нельзя их сразу записать в TFileStream?


 
Сергей
 
(2003-03-14 16:59)
[9]

Digitman ©: Сначала данные из текстового файла пишуться в динамический массив, а далее, чтобы каждый раз не загружать эти данные из текстового файла (потому что очень долго), я хочу их записывать в своем формате, в двоичном файле. Загрузка такого файла осуществляется гораздо быстрее. Вот.


 
Anatoly Podgoretsky
 
(2003-03-14 17:01)
[10]

Пока ты не скажешь про Sizeof(x) тебе никто не сможет ответить, но есть подозрение что это много.


 
Сергей
 
(2003-03-14 17:02)
[11]

Sizeof(x) Вычисляет размер буфера для одного элемента массива, ну правильнее будет Sizeof(x[i])


 
kDenis
 
(2003-03-14 17:03)
[12]



> Сергей



Ну напиши ты просто:

TMemoryStream.writebuffer(x,Sizeof(x));

Без всяких цыклов…



> Anatoly Podgoretsky ©

> theodor_iv ©



Хватит издиватся над человеком!


 
Digitman
 
(2003-03-14 17:05)
[13]



> Сергей

ну и что ?

что мешает выполнить в цикле «прямую» цепочку :

InFileStream (текст) -> нужное преобразование фрагмента -> OutFileStream(бинарный формат)

?


 
Anatoly Podgoretsky
 
(2003-03-14 17:07)
[14]

Сергей (14.03.03 17:02)

Да не что он вычитает, а сколько возвращает в твоем случае


 
Сергей
 
(2003-03-14 17:10)
[15]

Без всяких цыклов…

Не получиться, потому, что размер динамического массива функцией sizeOF не вычисляется.


 
Anatoly Podgoretsky
 
(2003-03-14 17:10)
[16]

Сергей (14.03.03 17:02)

Да и раз ты уже изменил показания, то давай новый правильный код со всеми данными

kDenis © (14.03.03 17:03)

Я очень сожалею по поводу твоего негодования, но ничем не могу помочь, только автор вопроса может ответить о размере X удобным ему способом. Мы же в отличии от тебя не телепаты


 
theodor_iv
 
(2003-03-14 17:10)
[17]



> kDenis ©

Кто здесь издЕвается — так это ты… А мы помочь пытаемся, хотя и разными методами :)



> Сергей



Моя мысль вполне здравая — зачем записывать динамический массив из оперативной памяти в оперативную память, а потом в файл, если можно записать сразу в файл и сэкономить 50 мег оперативки?


 
Anatoly Podgoretsky
 
(2003-03-14 17:11)
[18]

theodor_iv © (14.03.03 17:10)

Если твое предположение насчет 50 иб верное, то встает вопрос, а где взять 10 терабайт


 
theodor_iv
 
(2003-03-14 17:14)
[19]



> Anatoly Podgoretsky ©



Я так понял, что под фразой



> Данных где-то около 40-50Мб.



понимался суммарный объем, а не объем одного Х.


 
Сергей
 
(2003-03-14 17:14)
[20]

Anatoly Podgoretsky © (14.03.03 17:07):

Дело в том, что я написал немного упрощенно. x[i] — динамический массив записей. Каждая запись в свою очередь содержит динамические структуры.

Ну короче у меня получается загрузка и запись данных для объемов

5-10 мБ. Когда я использую входные текстовые данные больших размеров возникает эта ошибка.


 
Сергей
 
(2003-03-14 17:15)
[21]

theodor_iv © (14.03.03 17:14): Все правильно понимаете


 
Anatoly Podgoretsky
 
(2003-03-14 17:18)
[22]

Давай правильный код и размеры, иначе не ответить, но если у тебя 10иб, то посчитай сам 200 000 * 10 000 000, то это 10 терабайт, а виндоус поддерживает жля пользователя только 2 гигабайта виртуальной памяти в одном процессе.


 
theodor_iv
 
(2003-03-14 17:23)
[23]



> Сергей (14.03.03 17:15)

> theodor_iv © (14.03.03 17:14): Все правильно понимаете

Для того, чтобы создать такой поток, операционке нужно выделить более 50 мегабайт оперативной памяти одним непрерывным блоком, что является для нее нетривиальной задачей. :)

На мой взгляд, единственный выход — писать сразу в TFileStream, можно еще в сочетании с TCompressionStream.


 
Сергей
 
(2003-03-14 17:25)
[24]

Anatoly Podgoretsky © (14.03.03 17:18): Какие 10иб, кто это сказал? привожу код.

//Сохранение полигона в файл

procedure SavePolygon(Stream : TMemoryStream;Pol: TPolygon);

var SizePol: integer;

begin

SizePol:= Length(POl);

Stream.WriteBuffer(SizePol,SizeOf(Integer));//Пишем длину

Stream.WriteBuffer(PChar(POl)^,SizePol*SizeOf(TPoints));

end;

end;

//Сохранение свойств полигона

procedure TProjection.SavePolygonProp1(Stream : TMemoryStream;Prop: TPropPolygon);

var SizePol: LongInt;

begin

SizePol:= SizeOf(Prop);

Stream.WriteBuffer(Prop,SizePol);

end;

//Сохранение слоя в файл

procedure TProjection.SaveLayer1(Stream:TMemoryStream;L: TLayer);

var amPolygon: dword; //Число полигонов в слое

i: integer;

begin

amPolygon:=length(L.DataP);

Stream.WriteBuffer(amPolygon,SizeOf(amPolyGon));

for i:=1 to amPolygon do

begin

SavePolygon1(stream,L.DataP[i-1]);

SavePolygonProp1(stream,l.PolProp[i-1]);

end;

Stream.WriteBuffer(L.names,SizeOf(L.names));

Stream.WriteBuffer(L.vis,SizeOf(L.Vis));

end;

strm.SaveToFile(SaveDialog1.FileName);


 
Anatoly Podgoretsky
 
(2003-03-14 17:37)
[25]

Абсолютно другой код, чем в 16:25

Но точно также неясно насчет размеров записываемых элементов

Говорите точно сколько вам вешать, в байтах, память все таки.

Если не знаешь точно, то поступи так,

заведи переменную X

перед каждым Stream.WriteBuffer делай

X := X + размер;

Label1.Caption := IntToStr(X);

//Label2.Caption := IntToStr(I);

Application.ProcessMessages;

И узнаешь правду, до этого убедись, что на диске со своп файлом есть по крайней мере свободных 2 гб


 
Digitman
 
(2003-03-14 17:45)
[26]

вот ты ответь на простой вопрос — нахрена (!!) писать данные в память, когда в результате они тут же пишутся строчкой strm.SaveToFile(SaveDialog1.FileName); в файл ?? безо всякой промежуточной обработки ?? почему сразу не писать в FileStream ??


 
theodor_iv
 
(2003-03-14 17:49)
[27]



> Digitman © (14.03.03 17:45)

нахрена (!!) писать данные в память

Видимо, какую-то тайную цель преследует. Я тут уже об этом четыре раза сказал, но ответа не получил.


 
Anatoly Podgoretsky
 
(2003-03-14 17:55)
[28]

А я не получил ответа о размере данных, в тоже время жалоба на нехватку оной. Но может если проведет отладку по указанному сценарию то все таки сообщит.


 
Serginio
 
(2003-03-14 20:35)
[29]

У меня при размере > 80 000*4 байт поэтому для записи больших данных создал свой стрим основанный на массиве больших блоков памяти. А вообще то проблема с реалоками во всех объектах которые используют непрерывную память (TList,TStringList..) если хочешь вышлю.


  • Ошибка out of memory nokia
  • Ошибка out of memory nicehash
  • Ошибка out of memory matlab
  • Ошибка out of memori
  • Ошибка osu was unable to obtain a graphics context