Переменная с каким-то значением

  • Автор темы slavon-x86
  • Дата начала
S

slavon-x86

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

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

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

Yason

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

slavon-x86

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

Yason

Первый способ меня устраивает, но я не знаю как это сделать !
Кхм... Не знаешь -- читай. Матчасть правильно учить по .

Второй даёт утечку памяти в строках !
А по подробнее? В каких строках, при каком использовании, можно с кодом.
 
S

slavon-x86

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

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

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

slavon-x86

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

Код:
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.
 
Y

Yason

Во-первых, 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 с каким-нибудь скромным пределом, порядка сотни тысяч.
 
S

Silver Wind

Как вариант, чтобы не инициализировать каждое поле в записи по отдельности объяви типизированную константу в духе:
Код:
const
EmptyDataSpec: TDataSpec = (Avtive: 0; PageControl: 0; ...);

И используй в духе LocalDataSpec:=EmptyDataSpec;
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!