powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
18 сообщений из 18, страница 1 из 1
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508264
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте, помогите пожалуйста разобраться с выделением памяти.

Мне нужно передать содержимое Query по сети через HTTP, я решил выгрузить результат в память FDQuery.SaveToStream(fMemoryStream,sfBinary) и затем передать по сети, все работает, но вот в оперативке увеличивается занимаемая память:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
procedure TForm1.ExecSQL(fFDConnection: TFDConnection; fSQLText: String;
                         fisOpen:boolean; fFileName,fDelim:String; fBlockSize:Integer; 
                         fisStandartExport:Boolean;
                         var fError: String);
var
  qrTemp: TFDQuery;
  fMemoryStream:TMemoryStream;
begin
  try
    qrTemp := TFDQuery.Create(Self);
    with qrTemp do
      try
        Connection := fFDConnection;
        SQL.Text := fSQLText;
        if fisOpen then
        begin
          FetchOptions.CursorKind := ckForwardOnly;
          Open;
          if (fFileName <> '') then
          begin
            if fisStandartExport then
              SaveToFile(fFileName,sfBinary);
          end
          else
          begin
            fMemoryStream := TMemoryStream.Create;
            SaveToStream(fMemoryStream,sfBinary);
            SendData('192.168.1.1','', fMemoryStream,StrToIntDef(Edit3.Text,0),5,3,False,fProxyList);
          end;
          Close;
        end
        else
          ExecSQL;
      except
        on E:Exception do
          fError := 'ExecSQL-'+E.Message;
      end;
  finally
     FreeAndNil(qrTemp);
     if fFileName = '' then
       FreeAndNil(fMemoryStream);
  end;
end;

function TForm1.SendData(Server,FileName: String;
                         var MemStream:TMemoryStream;
                         KbBuff:integer; //Если 0, то весь файл
                         SleepTime:integer; //Интервал времени между отправками порций
                         maxCountErrorSend:integer; //Сколько раз отправлять в случае ошибки
                         isUseProxy:boolean;
                         ProxyList:TStringList): Integer;
var
  HTTP:THTTPSend;
  fFileSend:TFileStream; //Стим для файла который надо отправить
  fRangeStart, fRangeEnd:int64; //Позиции в файле для отправки
  fDataSize:int64; //Размер отправляемых данных (в байтах)
  fProxyRect:TProxyRect;//Proxy настройки
  i:integer;//Колчество порций kbBuff в fDataSize
  fCountError:Byte;
  fResult:integer;
  fCurrentProxy:Integer;
begin
  if not IsServerConnect(Server) then begin Result := -1; exit; end; //Сервер недоступен
  if FileName <> '' then  //Если передается файл
  begin
    if not FileExists(FileName) then begin Result := -2; exit; end; //Файл не найден
    try
      fFileSend := TFileStream.Create(FileName,fmOpenRead);
      fDataSize := fFileSend.Size;
    except
      try FreeAndNil(fFileSend); except end;
      Result := -3;//Не получили доступ к файлу
      exit;
    end
  end
  else //Если передаются данные из Query
  begin
    if MemStream.Size <= 0 then begin Result := -3; exit; end; //Stream не содержит данных
    fDataSize := MemStream.Size;
  end;
  if isUseProxy and Assigned(ProxyList) then //Заполняем список Proxy серверов
    GetProxyList(ProxyList);
  fRangeStart := 0;
  fRangeEnd := 0;
  i := 1;
  fCountError := 0;
  fResult := 0;
  fCurrentProxy := 0;
  fProxyRect.ProxyServer := '';
  HTTP := THTTPSend.Create;
  fProxyRect := GetOneProxy(fCurrentProxy,fProxyList);
  if KbBuff <= 0 then fRangeEnd := fDataSize;
  try
      repeat
          if KbBuff > 0 then
          begin
            fRangeEnd := i * KbBuff * 1024; //Высчитываем Position в потоке в зависимости от количества размера Буфера в Кб
            if fDataSize <= fRangeEnd  then //Если размер буфера превышает размер передаваемых данных
              fRangeEnd := fDataSize;
          end;
          if FileName <> '' then  //Если передается файл
            fFileSend.Position := fRangeStart //Переходим на нужную позицияю в файле
          else
            MemStream.Position := fRangeStart;
              //MemStream.Seek(fRangeStart,fRangeEnd);

          HTTP.Clear;//Очищаю соединение

          if (fResult <> 200) and isUseProxy then  //Если не прошло, то возможно из-за proxy
          begin
            inc(fCurrentProxy);
            fProxyRect := GetOneProxy(fCurrentProxy,fProxyList); //Получаем новый Proxy
          end;
          if isUseProxy and (fProxyRect.ProxyServer <> '') then //Заполняем Proxy
          begin
            HTTP.ProxyHost := fProxyRect.ProxyServer;
            HTTP.ProxyPort := fProxyRect.ProxyPort;
            HTTP.ProxyUser := fProxyRect.ProxyUser;
            HTTP.ProxyPass := fProxyRect.ProxyPassword;
          end;
          HTTP.UserAgent := 'Mozilla/5.0';
          HTTP.Headers.Add ('X-PosFD='+IntToStr(fRangeStart)+'-'+IntToStr(fRangeEnd));
          try
            if FileName <> '' then  //Если передается файл
              HTTP.Document.CopyFrom(fFileSend,fRangeEnd-fRangeStart)
            else
              HTTP.Document.CopyFrom(MemStream,fRangeEnd-fRangeStart);
            HTTP.HTTPMethod('GET', Server); //Отправляем данные
            fResult := HTTP.ResultCode;
          finally
            if fResult = 200 then
            begin
              inc(i); //сл порция
              fCountError := 0;
              fRangeStart := fRangeEnd;
            end
            else Inc(fCountError);
          end;
          Sleep(SleepTime*1000);
      until (fRangeEnd >= fDataSize) or (fCountError >= maxCountErrorSend);  //Пока не передали все
      Result := fResult;
  finally
    try HTTP.Free; except end;
    if FileName <> '' then
      try fFileSend.Free; except end;
  end;
end;



А вот что происходит в оперативке:
кб:
запуск: 2 740
FDConnection1.Connected := true;(MSAccess): 4 768
Query.Open: 5 648
SaveToStream(fMemoryStream,sfBinary): 43 744
Query.Close: 23 712
FreeAndNil(fMemoryStream): 15 892
FDConnection1.Connected := False: 15 764

Почему до SaveToStream память не увеличивалась вообще, а после сразу двукратно за query и fMemoryStream и после освобождения не вернулась к изначальному состоянию?

Модератор: Как мне оформить свое сообщение?
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508285
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist,

Код не смотрел, возможно есть нюансы. Несколько коментов.

авторПочему до SaveToStream память не увеличивалась вообще

попробуй сделать FetchAll, посмотришь.

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

считай, что освободилась.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508438
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaon,

в диспетчере задач видно, что память занята, почему так?
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508460
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, во-первых, замени своё
Sandist
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
var
  qrTemp: TFDQuery;
  fMemoryStream:TMemoryStream;
begin
  try
    qrTemp := TFDQuery.Create(Self);
    with qrTemp do
      try
        Connection := fFDConnection;
        SQL.Text := fSQLText;
        if fisOpen then
        begin
          FetchOptions.CursorKind := ckForwardOnly;
          Open;
          if (fFileName <> '') then
          begin
            if fisStandartExport then
              SaveToFile(fFileName,sfBinary);
          end
          else
          begin
            fMemoryStream := TMemoryStream.Create;
            SaveToStream(fMemoryStream,sfBinary);
            SendData('192.168.1.1','', fMemoryStream,StrToIntDef(Edit3.Text,0),5,3,False,fProxyList);
          end;
          Close;
        end
        else
          ExecSQL;
      except
        on E:Exception do
          fError := 'ExecSQL-'+E.Message;
      end;
  finally
     FreeAndNil(qrTemp);
     if fFileName = '' then
       FreeAndNil(fMemoryStream);
  end;
end;


на
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
var
  qrTemp: TFDQuery;
  fMemoryStream:TMemoryStream;
begin
  qrTemp := TFDQuery.Create(Self);
  try
    with qrTemp do
      try
        Connection := fFDConnection;
        SQL.Text := fSQLText;
        if fisOpen then
        begin
          FetchOptions.CursorKind := ckForwardOnly;
          Open;
          if (fFileName <> '') then
          begin
            if fisStandartExport then
              SaveToFile(fFileName,sfBinary);
          end
          else
          begin
            fMemoryStream := TMemoryStream.Create;
            try                 
              SaveToStream(fMemoryStream,sfBinary);
              SendData('192.168.1.1','', fMemoryStream,StrToIntDef(Edit3.Text,0),5,3,False,fProxyList);
            finally
              fMemoryStream.Free;
            end;
          end;
          Close;
        end
        else
          ExecSQL;
      except
        on E:Exception do
          fError := 'ExecSQL-'+E.Message;
      end;
  finally
     FreeAndNil(qrTemp);
  end;
end;


и думай, почему так, до просветления. А затем уже более сложными вопросами задавайся.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508461
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist,

и, да (на заметил сразу), делать локальные переменные равными nil в конце функции - бесполезная операция, достаточно вызова деструктора, или хотя бы .Free (для общей схемы), но это ладно.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508506
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
За except end; надо безжалостно отрывать руки.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508511
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,

спасибо за совет, но память так же не освобождается
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508514
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
или можете подсказать, как можно скопировать данные из quey в MemoryStream порциями? чтобы после передачи можно было так же подгрузить его в Query и осуществлять манипуляции
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508524
Фотография Dmitry Arefiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДВК-2 ?
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508546
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandistспасибо за совет, но память так же не освобождается
Если в диспетчере задач цифры не меняются - это не значит, что она не освобождается.
Выполни свою процедуру 1000000 раз и убедишься в этом (лубо в том, что она действительно не освобождается).
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508547
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist,

и еще. Если бы ты не использовал with в этой ф-ции - тебе было бы проще разобраться в своем коде. Не говоря уже об окружающих.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508552
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schiЗа except end; надо безжалостно отрывать руки.
Я кстати дальше код не смотрел. Потом посмотрел...
ТС, ты должен освобождать объекты, если они были созданы. А не по условию
Код: pascal
1.
if FileName <> '' then


Либо в начале создай объект, либо проинициализируй переменную nil вначале же (естественно, перед блоком try-finally). А затем можешь смело делать ей безусловное Free в блоке finally-end.

Блоки try-except используй не для того, чтобы подавить ошибку - это не поможет, а чтобы увидеть её в логе и в итоге исправить.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508554
Bred eFeM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist,
А вот что происходит в оперативке: ... в диспетчере задач видно, что память занятазаменить на
Код: pascal
1.
2.
3.
4.
program 
...
begin
  ReportMemoryLeaksOnShutdown := True;
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508672
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сколько бы раз я не вызывал процедуру память не увеличивается, останавливается на 15мб,
ReportMemoryLeaksOnShutdown - утечки не показывает
Можно сделать вывод, что диспетчер показывается неверные данные?

если в Finally написать так:
Код: pascal
1.
2.
if Assigned(fMemoryStream) then
fMemoryStream.Free;


это будет правильно?

Спасибо большое за помощь
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508685
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist,

используйте утилиту rammap для просмотра кусков памяти, занятых приложением.
SandistМожно сделать вывод, что диспетчер показывается неверные данные?
он просто не все показывает. Например, вам кажется что из 16 гиг 8 свободно, а на самом деле они используются виндой под кэш, и т.д.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508721
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SandistМожно сделать вывод, что диспетчер показывается неверные данные?
Он показывает верные данные. Но утечек при этом нет.


Sandistесли в Finally написать так:
Код: pascal
1.
2.
if Assigned(fMemoryStream) then
fMemoryStream.Free;



это будет правильно?
Если ты наведешь мышку на Free, нажмешь Ctrl и нажмешь левую кнопку мыши - ты зайдешь в исходник TObject.Free
и больше вопросов возникнуть не должно, как и дебильных проверок if Assigned then Free.

Ну а если в fMemoryStream неинициализированный мусор, а не nil - то никакие проверки не помогут.
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39508722
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandistесли в Finally написать так:
Код: pascal
1.
2.
if Assigned(fMemoryStream) then
fMemoryStream.Free;


это будет правильно?


Это будет неправильно, проверка на Assigned уже есть внутри .Free, правильно будет просто вызвать

Код: pascal
1.
fMemoryStream.Free;
...
Рейтинг: 0 / 0
FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
    #39509058
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не всё так просто с памятью, всё не так просто. Если утечек нет, то можно этими цифрами особенно не грузится.
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / FDQuery.SaveToStream(fMemoryStream,sfBinary) - память
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]