Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум программистов _ Delphi - Система _ Переменная с каким-то значением

Автор: slavon-x86 25:04:2008, 17:22

Код
procedure perem;
var
  i: integer;
begin
  ShowMessage(IntToStr(i));
end;


Выводит какое-то значение ! Т.е. создаётся непустая переменная. Кто знает почему, и как с эти бороться !

P.s. - обнулять по типу i := 0 тупо и неразумно; А если у меня ТИП данных, где 100 таких переменных, мне что их все по очереди обнулять ? Проверял на Delphi 7 и Delphi 2005 !



Автор: sax_ol 25:04:2008, 17:45

Цитата(slavon-x86 @ 25:04:2008 - 19:22) *
P.s. - обнулять по типу i := 0 тупо и неразумно;
Почему?
Цитата(slavon-x86 @ 25:04:2008 - 19:22) *
А если у меня ТИП данных, где 100 таких переменных
Какой такой тип?

Автор: slavon-x86 25:04:2008, 18:06

Цитата
Какой такой тип?

Вот такой !
Код
Type
  TDataSpec = record
    Avtive, PageControl, Count, ... тут штук 100 подобных переменных ..., Promo, Version: integer;
    Client: TClientArray;
  end;

vat
  Data: TSpecData;



Цитата
Почему?

Хм, много однако....


Автор: sax_ol 25:04:2008, 18:19

И что видно если так: ShowMessage(IntToStr(Data.Active));?

Автор: slavon-x86 25:04:2008, 18:25

Цитата
И что видно если так: ShowMessage(IntToStr(Data.Active));?


440006

Автор: sax_ol 26:04:2008, 06:10

Вы точно привели пример, или нет? Или вот киньте сюда тест, где такое есть, посмотрим.

Автор: slavon-x86 26:04:2008, 18:48

Нет, не точно. Я писал вот так:

Цитата
Memo1.Lines.Add(IntToStr(Data.Active));


Автор: Yason 26:04:2008, 19:58

slavon-x86
1. Сделай TDataSpec не record'ом, а классом, и в конструкторе инициализируй поля как хошь.
2. ZeroMemory(@data, sizeof(data))

Автор: slavon-x86 26:04:2008, 20:19

Первый способ меня устраивает, но я не знаю как это сделать !
Второй даёт утечку памяти в строках !

Автор: Yason 26:04:2008, 23:46

Цитата(slavon-x86 @ 27:04:2008 - 00:19) *
Первый способ меня устраивает, но я не знаю как это сделать !
Кхм... Не знаешь -- читай. Матчасть правильно учить по книжкам.

Цитата(slavon-x86 @ 27:04:2008 - 00:19) *
Второй даёт утечку памяти в строках !
А по подробнее? В каких строках, при каком использовании, можно с кодом.

Автор: slavon-x86 27:04:2008, 10:22

Цитата
А по подробнее? В каких строках, при каком использовании, можно с кодом.


Вот сорс ZeroMemory:
Код
procedure ZeroMemory(p:pointer;i:integer);
xor ecx,ecx
call FillChar
ret


В данном примере вызов процедуры FillChar проинициализирует строки пустыми значениями, такой подход был нормальным в ранних версиях Delphi и Borland Pascal, но недопустим в последних версиях, в которых тип string по умолчанию соответствует типу LongString и суть указатель. Если значения строк перед инициализацией были не пусты, то мы получим утечку памяти.

Автор: slavon-x86 27:04:2008, 12:36

Хотя я провёл тестирование и незаметил утечки...

Код
type
Tzzz = record
   s, s1, s2: string;
end;

var
  Form1: TForm1;
  counter: LongInt = 0;

implementation

uses Unit2;

{$R *.dfm}

procedure TestMemory;
var
  protocol : Tzzz;

begin
  randomize;

  FillChar(protocol, SizeOf(protocol), 0);

  protocol.s1 := IntToStr(random(999999));
  protocol.s2 := IntToStr(random(999999));

  if counter mod 1000 = 0 then Form1.Caption := IntToStr(counter);
  inc(counter);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  repeat
    TestMemory;
  until 1 = 2;
end;

end.

Автор: Yason 27:04:2008, 13:57

Во-первых, AnsiString создаётся пустой.
Во-вторых, если строку нужно (пере)инициализировать заново, это делается безо всяких ZeroMemory:

Код
s := '';

Применение ZeroMemory ещё можно придумать при работе с PChar, но AnsiString всё делает самостоятельно.

slavon-x86
Утечки памяти нет только потому, что Вы сначала создаёте protocol (неинициализированный), потом его зачищаете FillChar'ом, и только потом присваиваете осмысленные значения. После чего процедура заканчивается, protocol удаляется из стека вместе со своими полями, и никакой памяти не теряется.

А попробуйте в другом порядке
Код
  protocol.s1 := IntToStr(random(999999));
  protocol.s2 := IntToStr(random(999999));
  FillChar(protocol, SizeOf(protocol), 0);

или сделайте protocol глобальной переменной. Потом запустите Task Manager, и посмотрите на потребление памяти.

P.S. Очень советую на время экспериментов repeat заменить на for с каким-нибудь скромным пределом, порядка сотни тысяч.

Автор: Silver Wind 28:04:2008, 05:47

Как вариант, чтобы не инициализировать каждое поле в записи по отдельности объяви типизированную константу в духе:

Код
const
EmptyDataSpec: TDataSpec = (Avtive: 0; PageControl: 0; ...);


И используй в духе LocalDataSpec:=EmptyDataSpec;

Русская версия Invision Power Board (http://www.nulled.ws)
© Invision Power Services (http://www.nulled.ws)