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

Тема в разделе "Delphi - Система", создана пользователем slavon-x86, 25 апр 2008.

  1. slavon-x86

    slavon-x86 Well-Known Member

    Регистрация:
    18 дек 2005
    Сообщения:
    216
    Симпатии:
    0
    Код (Text):
    procedure perem;
    var
    i: integer;
    begin
    ShowMessage(IntToStr(i));
    end;
    Выводит какое-то значение ! Т.е. создаётся непустая переменная. Кто знает почему, и как с эти бороться !

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

    slavon-x86 Well-Known Member

    Регистрация:
    18 дек 2005
    Сообщения:
    216
    Симпатии:
    0
    Вот такой !
    Код (Text):
    Type
    TDataSpec = record
    Avtive, PageControl, Count, ... тут штук 100 подобных переменных ..., Promo, Version: integer;
    Client: TClientArray;
    end;

    vat
    Data: TSpecData;

    Хм, много однако....
     
  3. slavon-x86

    slavon-x86 Well-Known Member

    Регистрация:
    18 дек 2005
    Сообщения:
    216
    Симпатии:
    0
    440006
     
  4. slavon-x86

    slavon-x86 Well-Known Member

    Регистрация:
    18 дек 2005
    Сообщения:
    216
    Симпатии:
    0
    Нет, не точно. Я писал вот так:
     
  5. Yason

    Yason Гость

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

    slavon-x86 Well-Known Member

    Регистрация:
    18 дек 2005
    Сообщения:
    216
    Симпатии:
    0
    Первый способ меня устраивает, но я не знаю как это сделать !
    Второй даёт утечку памяти в строках !
     
  7. Yason

    Yason Гость

    Кхм... Не знаешь -- читай. Матчасть правильно учить по книжкам.

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

    slavon-x86 Well-Known Member

    Регистрация:
    18 дек 2005
    Сообщения:
    216
    Симпатии:
    0
    Вот сорс ZeroMemory:
    Код (Text):
    procedure ZeroMemory(p:pointer;i:integer);
    xor ecx,ecx
    call FillChar
    ret
    В данном примере вызов процедуры FillChar проинициализирует строки пустыми значениями, такой подход был нормальным в ранних версиях Delphi и Borland Pascal, но недопустим в последних версиях, в которых тип string по умолчанию соответствует типу LongString и суть указатель. Если значения строк перед инициализацией были не пусты, то мы получим утечку памяти.
     
  9. slavon-x86

    slavon-x86 Well-Known Member

    Регистрация:
    18 дек 2005
    Сообщения:
    216
    Симпатии:
    0
    Хотя я провёл тестирование и незаметил утечки...

    Код (Text):
    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.
     
  10. Yason

    Yason Гость

    Во-первых, AnsiString создаётся пустой.
    Во-вторых, если строку нужно (пере)инициализировать заново, это делается безо всяких ZeroMemory:
    Код (Text):
    s := '';
    Применение ZeroMemory ещё можно придумать при работе с PChar, но AnsiString всё делает самостоятельно.

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

    А попробуйте в другом порядке
    Код (Text):
     protocol.s1 := IntToStr(random(999999));
    protocol.s2 := IntToStr(random(999999));
    FillChar(protocol, SizeOf(protocol), 0);
    или сделайте protocol глобальной переменной. Потом запустите Task Manager, и посмотрите на потребление памяти.

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

    Silver Wind Гость

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

Поделиться этой страницей