На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Глобальные переменные , глюк инициализации
    Глобальные переменные вроде как инициализируются нулевыми значениями.
    Даже в хелпе написано: "If you don't explicitly initialize a global variable, the compiler initializes it to 0."
    Почему же тогда...

    ExpandedWrap disabled
      {$APPTYPE CONSOLE}
      var
        X, Y, Z: Integer;
       
      begin
        WriteLn(X);
        WriteLn(Y);
        WriteLn(Z);
      end.
    ...выдаёт...
    ExpandedWrap disabled
      2130567168
      0
      0
    ???

    А компилер пишет:
    ExpandedWrap disabled
      a.pas(6) Warning: W1036 Variable 'X' might not have been initialized
      a.pas(7) Warning: W1036 Variable 'Y' might not have been initialized
      a.pas(8) Warning: W1036 Variable 'Z' might not have been initialized


    Где косяк? :huh:

    А вот код...
    ExpandedWrap disabled
      unit a;
      interface
      var X, Y, Z: Integer;
      implementation
      end.

    ExpandedWrap disabled
      {$APPTYPE CONSOLE}
      uses a;
      begin
        WriteLn(X);
        WriteLn(Y);
        WriteLn(Z);
      end.

    Не выдаёт никаких warning'ов и выдаёт нули (может, совпадение, конечно, уж не знаю).

    При этом я беру какую-нибудь случайную свою программу, добавляю в начало WriteLn какой-то переменной - warning'а нет... Добавляю в другую - есть. Короче, непонятно...

    p.s. Delphi 7, Delphi 2007, Delphi 10.1.
      Цитата Jin X @
      If you don't explicitly initialize a global variable, the compiler initializes it to 0

      Это где написано?
        Jin X
        Зайди в отладчик в D7 и прослезись. Там кодогенератор на творил чёрти что и сбоку бантик.
        Он в edx(вернее ebx, esi,edi) забыл положить значение из переменной и выводит просто мусор.

        Я тут свой компилятор паскаля пишу. Так вот с кодогенерацией там весело. Никогда не знаешь что ты там забыл добавить и где-что сломается. Даже тесты это не всегда показывают.

        Цитата Jin X @
        Не выдаёт никаких warning'ов и выдаёт нули (может, совпадение, конечно, уж не знаю).

        Это какое-то совпадение. В том смысли что наличие и отсутствие warning может зависеть от версии компилятора и установленных плагинов. Может ещё и от настроек проекта.
        Сообщение отредактировано: Pavia -
          >Это где написано?
          http://docwiki.embarcadero.com/RADStudio/T...iables_(Delphi)


          >Почему же тогда...
          В XE3 нули в Debug, мусор в первой переменной (даже если изменять их количество) в Release.
          Видимо, дефект.
            Цитата Jin X @
            Где косяк?

            Видимо дело в том, что begin..end проекта в действительности является процедурой и соотв-но переменные, объявленные в проекте, хоть и выглядят как глобальные, на самом деле являются локальными переменными этой процедуры.

            Добавлено
            Цитата Fr0sT @
            Это где написано?

            Написано в справке. На самом деле никакой специальной инициализации нулями не делается, т.к. это получается автоматически - просто винда для секции неинициализированных данных (BSS) по дефолту выделяет обнуленные страницы памяти.
              Цитата Pavia @
              Это какое-то совпадение. В том смысли что наличие и отсутствие warning может зависеть от версии компилятора и установленных плагинов. Может ещё и от настроек проекта.
              Я думаю, тут прикол в том, что при компиляции модуля dcc не знает где эти переменные будут использоваться. А при компиляции программы dcc не знает, была ли проинициализирована переменная в модуле :)
              Хотя, вот такая штука выдаёт нули (без ворнингов):
              ExpandedWrap disabled
                unit a;
                interface
                var X, Y, Z: Integer;
                implementation
                 
                begin
                  WriteLn(X);
                  WriteLn(Y);
                  WriteLn(Z);
                end.


              Цитата leo @
              Видимо дело в том, что begin..end проекта в действительности является процедурой и соотв-но переменные, объявленные в проекте, хоть и выглядят как глобальные, на самом деле являются локальными переменными этой процедуры.
              ИМХО, локальные переменные - это переменные в стеке (для процедур). А так ещё переменные внутри класса могут быть и т.п. Все остальные - глобальные. А тут обращение идёт как раз к переменной (посмотрел сейчас специально через отладчик).

              Цитата leo @
              На самом деле никакой специальной инициализации нулями не делается, т.к. это получается автоматически - просто винда для секции неинициализированных данных (BSS) по дефолту выделяет обнуленные страницы памяти.
              Почему же тогда здесь не нули?
              Или дело в...
              Цитата Pavia @
              Зайди в отладчик в D7 и прослезись. Там кодогенератор на творил чёрти что и сбоку бантик.
              Он в edx(вернее ebx, esi,edi) забыл положить значение из переменной и выводит просто мусор.
              ???
                Jin X
                user posted image
                Сообщение отредактировано: Pavia -
                  Цитата Jin X @
                  Все остальные - глобальные. А тут обращение идёт как раз к переменной (посмотрел сейчас специально через отладчик).

                  И что увидел?
                  Pavia прав - первые три переменные (по какой-то причине, скорее всего - какой-то доисторической совместимости) как-бы "передаются" через регистры ebx, esi, edi, но на самом деле они не инициализированы и содержат мусор. Остальные - как положено читаются из памяти и соотв-но содержат нули.

                  Добавлено
                  Цитата Jin X @
                  ИМХО, локальные переменные - это переменные в стеке (для процедур). ... Все остальные - глобальные.

                  С точки зрения языка локальные переменные - это те, что объявлены внутри функций, а где они конкретно размещаются в памяти это, как говорится, implementation specific. Соотв-но, глобальные переменные - это те, что объявлены вне каких-либо функций. НО, на что я обращаю внимание, что по идее весь код программы состоит только из функций, соотв-но все специфические дельфийско-паскалевские фишки\плюшки типа begin-end в файле проекта или секции initialization \ finalization в юнитах по сути также являются функциями (процедурами). Т.е. весь код dpr-файла по сути является функцией и все var-переменные в этом файле можно считать "локальными" (не по способу размещения в памяти, а по области видимости - кроме функции begin-end проекта их все равно никто не видит). Видимо поэтому компилятор и считает их локальными и выдает варнинги при отсутствии их явной инициализации (и как видим - не зря). Другое дело, что эта хитрость\особенность dpr-файла не описана в справке - это да, реальный косяк
                  Сообщение отредактировано: leo -
                    Цитата leo @
                    И что увидел?
                    Pavia прав - первые три переменные (по какой-то причине, скорее всего - какой-то доисторической совместимости) как-бы "передаются" через регистры ebx, esi, edi, но на самом деле они не инициализированы и содержат мусор. Остальные - как положено читаются из памяти и соотв-но содержат нули.
                    Да, точно. Видимо, я не те данные зацепил (смотрел через x32dbg зачем-то)... :facepalm:

                    Цитата leo @
                    типа begin-end в файле проекта или секции initialization \ finalization в юнитах по сути также являются функциями (процедурами). Т.е. весь код dpr-файла по сути является функцией и все var-переменные в этом файле можно считать "локальными" (не по способу размещения в памяти, а по области видимости - кроме функции begin-end проекта их все равно никто не видит). Видимо поэтому компилятор и считает их локальными и выдает варнинги при отсутствии их явной инициализации (и как видим - не зря).
                    Короче, прикол вот в чём. Часть переменных (в данном случае - первые 3, если мы не пытаемся, например, получить их адрес) размещаются в регистрах. Остальное - в области глобальных переменных.
                    ExpandedWrap disabled
                      {$APPTYPE CONSOLE}
                      var
                        A, B, C, D, E, F: Integer;
                       
                      begin
                        asm
                          lea edi,A
                          mov eax,1
                          stosd
                          inc eax
                          stosd
                          inc eax
                          stosd
                          mov ebx,10
                          mov esi,20
                          mov edi,30
                        end;
                        WriteLn(A);
                        WriteLn(B);
                        WriteLn(C);
                        WriteLn(D);
                        WriteLn(E);
                        WriteLn(F);
                        ReadLn;
                      end.
                    выдаёт
                    ExpandedWrap disabled
                      1
                      10
                      20
                      30
                      2
                      3

                    Теперь следующий прикол: обращение к переменной из модуля происходит не напрямую, а через указатель!
                    Т.е. присвоение X := 1 выполняется как mov [X],1 только внутри модуля, а извне (из главной программы) - вот так:
                    ExpandedWrap disabled
                      mov eax,X_addr
                      mov [eax],1
                    Зачем так было мудрить? :-?

                    Добавлено
                    При этом, кстати, можно спокойно сделать вот так:
                    ExpandedWrap disabled
                       asm
                          mov X,1
                        end
                    И там будет именно mov [X],1 :lol:
                    И это всё как в 7, так и в Берлине происходит.
                    Зачем тогда так усложнять X := 1 ??? В чём прикол?

                    Добавлено
                    Вот в этом коде (даже при том, что Test никогда не вызывается) все переменные будут находиться в памяти (т.е. будут реальными глобальными переменными).

                    ExpandedWrap disabled
                      {$APPTYPE CONSOLE}
                      var X, Y, Z: Integer;
                       
                      procedure Test;
                      begin
                        X := 1;
                        Y := 2;
                        Z := 3;
                      end;
                       
                      begin
                        WriteLn(X);
                        WriteLn(Y);
                        WriteLn(Z);
                      end.


                    Добавлено
                    Соответственно, если мы убираем строку Z := 3, эта переменная становится локальной :facepalm:
                      По поводу ссылок на переменные внешних модулей: http://www.transl-gunsmoker.ru/2011/08/hac...als-faster.html
                      По ходу, я теперь в каждую свою прогу беде добавлять опцию {$G-} (по крайней мере, компилируемую в Delphi7) :D

                      Добавлено
                      Кстати, при создании объекта, все его поля очищаются.
                      ExpandedWrap disabled
                        class function TObject.InitInstance(Instance: Pointer): TObject;
                        {$IFDEF PUREPASCAL}
                        var
                          IntfTable: PInterfaceTable;
                          ClassPtr: TClass;
                          I: Integer;
                        begin
                         FillChar(Instance^, InstanceSize, 0);
                          PInteger(Instance)^ := Integer(Self);
                          ClassPtr := Self;
                          while ClassPtr <> nil do
                          begin
                            IntfTable := ClassPtr.GetInterfaceTable;
                            if IntfTable <> nil then
                              for I := 0 to IntfTable.EntryCount-1 do
                          with IntfTable.Entries[I] do
                          begin
                            if VTable <> nil then
                              PInteger(@PChar(Instance)[IOffset])^ := Integer(VTable);
                          end;
                            ClassPtr := ClassPtr.ClassParent;
                          end;
                          Result := Instance;
                        end;
                        Это замаскированный стимул избегать глобальных переменных елико возможно)
                          Fr0sT, :good: :lol:
                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0485 ]   [ 17 queries used ]   [ Generated: 23.04.24, 18:17 GMT ]