Как узнать какая ошибка delphi

Допустим, сделана опечатка и неправильно написано какое-нибудь ключевое слово. В этом случае при попытке запуска программы внизу появляется окно, в котором отображены сообщения об ошибках. При этом программа не запустится. Благодаря подсказке такую ошибку легко найти и исправить.

Частой ошибкой начинающих является пропуск конструкции begin – end в цикле. При
этом имеется в виду, что в цикле должны выполняться, например, обе команды, но на самом-то деле в цикле, конечно, будет выполняться только первая, а вторая выполнится только один раз – потом, когда программа выйдет из цикла. При попытке запуска появляется сообщение. Но это не ошибка, а предупреждение. В нем обращается внимание на то, что параметр цикла после выполнения цикла может быть неопределенным (он присутствует во второй команде).

Однако, несмотря на предупреждение, программа может запуститься. Если вводятся
дкакие-либо данные, то появляется сообщение об исключительной ситуации – exception. При этом программа приостанавливается, переходя из режима исполнения в режим отладки. Чтобы перейти к обычному редактированию кода, лучше остановить программу. Это можно сделать с помощью команды Program Reset. Затем можно поправить ошибку и вновь запустить программу.

В большие программы всегда закрадываются ошибки. Их надо быстро и квалифицированно найти и исправить.

Механизм исключительных ситуаций (exception)
одно из больших достоинств Delphi. С их помощью вы можете контролировать
возникновение ошибок и создавать в результате устойчивые к ошибкам программы.

По мере знакомства с языком и средой программист проходит несколько этапов. На
первом этапе он, по незнанию, путает типы, забывает ставить знаки препинания (например, точку с запятой в конце строки), некорректно использует операторы и т.п. В результате написанный им код в принципе невозможно исполнить. И это хорошо – 15 поскольку допущенные им ошибки оказываются автоматически выявленными на этапе компиляции, более того, часто среда программирования сама подсказывает, какая ошибка допущена, и, что важно, указывает строку, которую нужно поправить. По мере изучения языка и борьбы с синтаксическими ошибками программист плавно переходит к следующему этапу. Теперь он уже не делает таких простейших ошибок, но, поскольку сложность его программ возрастает, возрастает и вероятность совершения им ошибки, при которой программа все равно запустится. Поскольку, с точки зрения компилятора, явной ошибки нет, а некоторые странности кода, по-видимому, являются замыслом программиста. Однако компилятор все-таки сообщает об этих странностях с помощью предупреждений (Warning).

Советуем всегда обращать на них внимание, проверять при их появлении, нет ли ошибки, и вообще стараться писать код так, чтобы не было предупреждений.

Опасность таких скрытых ошибок состоит:

1) в том, что они таятся в той части кода, которую программист написал и уверен, что
она правильная (программа запустилась), а значит, и не очень внимательно будет
искать ошибку;

2) в том, что проявляется эта ошибка совсем в другом месте кода – не в том, в котором
допущена. А это приводит к долгим поискам ее по всей программе.

При возникновении исключительной ситуации можно проигнорировать ее и запустить
исполнение программы дальше, нажав F9. В этом случае программа выдает сообщение об ошибке. Необходимо найти ошибку – понять, в какой строке и почему происходит сбой. Для этого можно воспользоваться трассировкой. Для того чтобы определить первую строчку, начиная с которой будет проводиться трассировка, нужно поставить Breakpoint – точку останова.

Когда исполняемый код доходит до точки останова, исполнение программы
приостанавливается, и надо перейти в режим отладки. В режиме отладки можно исполнять последовательно программу по шагам, контролировать и изменять значения переменных и т.п. Этот режим служит для обнаружения и ликвидации ошибок. В этом случае появляется возможность просмотреть или изменить текущие значения переменных, однако изменение кода во время отладки невозможно. Измененный текст заработает только после перезапуска программы.

Чтобы выполнить текущую строку, на которой стоит курсор отладки, нажмите F7 или
F8. Строка выполнилась, и курсор сместился. Если необходимо перейти к следующей строке, то можно нажать F8, если нужно зайти в какую-либо функцию, то нажимают клавишу F7 и продолжают трассировку.

Для того чтобы в ходе отладки узнать значение той или иной переменной, нужно просто подвести к ней курсор. Появится hint со значением этой переменной. Это, однако, работает не со всеми переменными, а только с доступными в данный момент. Если нужно постоянно контролировать значение переменной, то еще проще добавить ее в список Watch.

Для более основательного слежения за значениями можете воспользоваться Списком Наблюдения (Watch List, Ctrl+F5).

Таким образом, при программировании среда Delphi может находиться в различных
режимах:

• Режим редактирования – режим, в котором редактируется код проекта,
модифицируется форма, добавляя на нее компоненты и настраивая их свойства. Это
основной режим.

• Режим исполнения программы – режим, в который среда переходит, как только
нажата клавиша F9 и был построен exe-файл. Фактически, в этом режиме происходиткак раз исполнение получившегося exe-файла проекта. Программа исполняется так,
как если бы ее вызвали не из Delphi, а просто из Windows.

• Режим отладки – в этот режим можно перейти из режима исполнения программы.

При этом программа будет приостановлена (но не остановлена совсем).

Чтобы продолжить трассировку (последовательный переход от команды к команде),
можете воспользоваться клавишами:

• F9 (Run) – продолжить программу, не трассируя ее.

• F8 (Step over) – выполняется текущая строка кода, и переходят к следующей строке.

• F7 (Trace Into) – то же, что и F8, с тем отличием, что если в текущей строчке
содержится вызов какой-либо функции или процедуры, то попадают внутрь этой
процедуры и трассируют ее до конца, затем из нее возвращаетс и переходят к
следующей строке (на которую перешли бы сразу, если бы нажали F8).

• F4 (Run to Cursor) – переход в режим исполнения программы до тех пор, пока не
должна будет выполнена строка, на которой стоит текстовый курсор (аналогично
тому, как если бы была установлена точка останова)

• Shift+F8 (Run Until Return) – процедура выполняется до конца.

• Ctrl+F2 (Program Reset) – остановка трассировки и переход в режим редактирования
кода. (Иногда целесообразнее, если это не грозит ошибками, продолжить исполнение
программы (F9) и выйти из нее нормальным образом, закрыв главную форму).

При работе в Delphi сообщение об ошибке фактически появляется дважды: сначала
выводится окно об исключительной ситуации и программа приостанавливается, а потом,
если нажать F9 (F8, F7 и т.п.), – возникает стандартное сообщение об ошибке Windows.

Итак:

1. Произошла ошибка.

2. Программа приостанавливается.

3. Выводится сообщение об exception. Это сообщение для программиста. Среда Delphi
сообщает, что программа не в состоянии выполнить какую-то свою команду.
Программист не предусмотрел возможность исключительной ситуации. Среда Delphi
приостанавливает программу, чтобы программист разобрался, где и в чем ошибка.
Отключить приостановку (2)–(3) можно, сняв флажок Menu => Tools => Debugger
Options => Language Exceptions => Stop on Delphi Exceptions.

4. Нажатие клавиши F9 (F8, F7 или др.).

5. Выводится сообщение об ошибке. Это сообщение для пользователя программы
(ситуация запуска приложения не из Delphi, а через exe-файл из Windows, т.е. не
существовует пунктов 2, 3, 4).

6. Программа продолжается (при этом она не сумела выполнить ту часть, в которой
произошла ошибка, и значит, если эта часть важная, продолжение может
сопровождаться дальнейшими ошибками).

Механизм обработки исключительных ситуаций заключается в том, что если
произошла ошибка (1) и не надо выводить (5), предпринимаются действия, чтобы (6) исполнялось корректно.

Для этого «опасная» команда (или целый блок) помещается внутрь конструкции try..except..end или try..finally..end.

Блок try..finally..end используется аналогично try..except.., но с тем отличием, что блок
команд между finally и end выполняется в любом случае, вне зависимости от того, было исключение между try и finally или нет.

>
Как узнать код ошибки try except

  • Подписаться на тему
  • Сообщить другу
  • Скачать/распечатать тему



Сообщ.
#1

,
27.10.09, 12:43

    Senior Member

    ****

    Рейтинг (т): 3

    Подскажите, можно ли как нибудь отловить код ошибки?
    Объясняю на примере:
    Вот отлавливает деление на ноль, к примеру:

    ExpandedWrap disabled

      //readln(A);  =0;

      try

      Z:=Z/A;

      except on E: exception do

      ShowMessage(e.messages);

      end;

    Ну это конечно ясно, что он напишет ‘Division by zero’, но это во-первых по английски, а во вторых, если мы напишем сразу сообщение по русски, т.е. так:

    ExpandedWrap disabled

      //readln(A);  =0;

      try

      Z:=Z/A;

      except

      ShowMessage(‘Деление на ноль!’);

      end;

    и допустим, что ошибка произошла не из-за того, что делится на ноль, а из-за чего-нибудь другова — то естественно сообщение будет ложным, а точнее неверным.
    И что делать? Типа есть такой вариант, но тупой:

    ExpandedWrap disabled

      //readln(A);  =0;

      try

      Z:=Z/A;

      except on E: exception do

      if (e.messages=’Division by zero’) then ShowMessage(‘Деление на ноль’) else

      ShowMessage(e.messages);

      end;

    Почему вариант тупой, да потому что, перед тем как вставить текст сообщения об ошибке надо:
    1. Сделать эту ошибку
    2. вывести её на экран
    3. скопировать её текст «символ в символ»
    4. потом вставить это сообщение в код для сравнения.

    Хочется что-то типа того, что текст ошибки сообщения мог бы заменять какой-нибудь её индетификатор, чтобы можно было типа такого:

    ExpandedWrap disabled

      //readln(A);  =0;

      try

      Z:=Z/A;

      except on E: exception do

      if (e.код_ошибки=123) then ShowMessage(‘Деление на ноль’) else

      ShowMessage(e.messages);

      end;

    где «123» есть индетификатор ошибки, т.е. заменяет сам текст ‘Division by zero’. Да, и у e нет параметра на английском, что я написал на русском код_ошибки.

    Ууууу…. Пока писал — сам устал. :)
    Если кто поймёт меня, помогите разобраться.


    CodeMonkey



    Сообщ.
    #2

    ,
    27.10.09, 12:52

      ExpandedWrap disabled

        on E: EDivByZero do

      Подробно и в деталях.


      Continental



      Сообщ.
      #3

      ,
      27.10.09, 14:21

        Senior Member

        ****

        Рейтинг (т): 3

        Спасибо за ссылку.
        А вот в каком модуле находятся классы исключений при работе с ibx компонентами.
        Т.е. мне надо вот к примеру такой класс исключения:

        ExpandedWrap disabled

          except

                    on E: EIBInterBaseError do begin

                          sShowMessage(e.ClassName,e.Message);

                          exit;

                          end;

        а он мне пишет: Неизвестная переменная EIBInterBaseError

        Вообще класс такой есть, он даже его показывает, если я делаю так:

        ExpandedWrap disabled

                  try

                  Connected:=true;

                  except

                    on E: exception do

                          sShowMessage(e.ClassName,e.Message);

                    end;

        Вот e.ClassName как раз и есть EIBInterBaseError, только я не могу класс коде указать.

        Сообщение отредактировано: Continental — 27.10.09, 14:48


        mitrich



        Сообщ.
        #4

        ,
        27.10.09, 14:57

          Senior Member

          ****

          Рейтинг (т): 99

          Хелп говорит, что EIBInterBaseError находится в юните IB


          CodeMonkey



          Сообщ.
          #5

          ,
          27.10.09, 14:59

            Цитата Continental @ 27.10.09, 14:21

            А вот в каком модуле находятся классы исключений при работе с ibx компонентами.

            Пуск/Поиск. *.pas с текстом EIBInterBaseError.
            Для ускорения поиска лучше ткнуть в папку Delphi.

            Цитата Continental @ 27.10.09, 14:21

            Вообще класс такой есть, он даже его показывает, если я делаю так

            Вместо

            ExpandedWrap disabled

              except

                on E: SomeClass do

                …

            можно (но не рекомендуется) использовать:

            ExpandedWrap disabled

              except

                on E: Exception do

                  if E.ClassName = ‘SomeClass’ then

                    …

                  else

                    raise;


            Continental



            Сообщ.
            #6

            ,
            27.10.09, 15:51

              Senior Member

              ****

              Рейтинг (т): 3

              ММММ…. всё равно прочитав всё, не могу реализовать то что я хочу.
              Вот к примеру:
              1. я указываю несуществующий путь к БД в TIBDataBase. Делаю подключение и try показывает ошибку класса EIBDataBaseError, при этом вот такой текст ошибки: ‘IO Error ….и т.д.’.
              2. я указываю существующий путь к БД в TIBDataBase. Указываю неверный логин или верный логин, но неверный пароль и мне ошибка класса EIBDataBaseError, но текст сообщения уже другой! Текст такой: ‘Your user name …. are not defined. …’.

              Так вот я хочу сказать, что в двух случаях ошибки совсем разные, а вот класс исключения один и тот же.
              Так я не могу понять, как же мне отловить первую ошибку, или вторую вот с помощью такой конструкции:

              ExpandedWrap disabled

                        try

                        IBDataBase.Connected:=true;

                        except

                          on E : что здесь должно быть, чтобы определить 1-й случай? do begin

                             sShowMessage(‘несуществующий путь бд!’);

                             exit;

                             end;

                          on E : что здесь должно быть, чтобы определить 2-й случай? do begin

                             sShowMessage(‘неверный пользователь или пароль’);

                             exit;

                             end;

                          on E : Exception do begin //люая другая ошибка

                             sShowMessage(e.ClassName,E.Message+’ совершенно другая ошибка’);

                             exit;

                             end;

                          end;

              Помогите разобраться пожалуйста, я очень хочу сделать так, но не знаю.


              CodeMonkey



              Сообщ.
              #7

              ,
              27.10.09, 16:11

                Цитата Continental @ 27.10.09, 15:51

                Так вот я хочу сказать, что в двух случаях ошибки совсем разные, а вот класс исключения один и тот же.

                Если у вашего EIBDataBaseError нет какого-нибудь IBErrorCode — то это криво спроектированные классы Interbase.

                Цитата Continental @ 27.10.09, 15:51

                Так я не могу понять, как же мне отловить первую ошибку, или вторую вот с помощью такой конструкции:

                Если никакого поля с кодом нет, то по-хорошему — никак.

                (Т.е. вы можете, конечно, попробовать анализировать сообщение, но ведь его могут локализовать).

                Добавлено 27.10.09, 16:13
                P.P.S.
                Если же поле кода есть, то в общем случае как-то так:

                ExpandedWrap disabled

                  try

                    IBDataBase.Connected:=true;

                  except

                    on E: EIBDataBaseError do

                      if E.ErrorCode = XXX then

                      begin

                        sShowMessage(‘несуществующий путь бд!’);

                        exit;

                      end

                      else

                      if E.ErrorCode = YYY then

                      begin

                        sShowMessage(‘неверный пользователь или пароль’);

                        exit;

                      end

                      else

                        raise;

                  end;

                Добавлено 27.10.09, 16:15
                Или:

                ExpandedWrap disabled

                  try

                    IBDataBase.Connected:=true;

                  except

                    on E: Exception do

                    begin

                      if E is EIBDataBaseError then

                      begin

                        if EIBDataBaseError(E).ErrorCode = XXX then

                        begin

                          sShowMessage(‘несуществующий путь бд!’);

                          exit;

                        end

                        else

                        if EIBDataBaseError(E).ErrorCode = YYY then

                        begin

                          sShowMessage(‘неверный пользователь или пароль’);

                          exit;

                        end;

                      end;

                      ShowMessage(e.ClassName,E.Message+’ совершенно другая ошибка’);

                    end;

                  end;

                Добавлено 27.10.09, 16:17
                P.P.P.S. Но в общем и целом, если вам это нужно только для показа сообщения об ошибке «на русском», то лучше бы вам локализовать константы вместо того, чтобы ставить кучу обработчиков по всей программе.


                mitrich



                Сообщ.
                #8

                ,
                27.10.09, 16:46

                  Senior Member

                  ****

                  Рейтинг (т): 99

                  Цитата CodeMonkey @ 27.10.09, 16:11

                  Если у вашего EIBDataBaseError нет какого-нибудь IBErrorCode

                  Именно так это свойство и называется, что нетрудно узнать из хелпа (который надеется на длительное и плодотворное сотрудничество с Continental :) )
                  Значения этих кодов прописаны в файле IBErrorCodes.pas (ищи его где-нибудь в C:Program FilesBorlandDelphi7SourceVclIBErrorCodes.pas, к примеру)


                  Continental



                  Сообщ.
                  #9

                  ,
                  27.10.09, 16:47

                    Senior Member

                    ****

                    Рейтинг (т): 3

                    С облегчением … :)

                    ExpandedWrap disabled

                              try

                              Connected:=true;

                              except

                                on E : EIBInterBaseError do begin

                                   sShowMessage(IntToStr(e.IBErrorCode),E.Message);

                                   exit;

                                   end;

                    Спасибо всем, что открыли глаза.

                    Добавлено 27.10.09, 17:01
                    О! вообще круто! CodeMonkey, спасибо что подсказали вот это

                    ExpandedWrap disabled

                      except

                        on E: Exception do

                        begin

                          if E is EIBDataBaseError then

                          begin

                            if EIBDataBaseError(E).ErrorCode = XXX then

                    Я теперь это заделал в applicationevents. Теперь у меня будет и лог вестись и сообщения об ошибках выводится! Е-Е-Е!


                    CodeMonkey



                    Сообщ.
                    #10

                    ,
                    27.10.09, 18:18

                      Для лога ошибок имеет смысл использовать хук на исключения. См. JCL, EurekaLog, madExcept. Помимо сообщения этот способ позволит получить стек вызовов и состояние процессора в момент ошибки. С этой информацией зачастую продиагностировать ошибку можно даже не запуская отладчик.

                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                      0 пользователей:

                      • Предыдущая тема
                      • Delphi: Общие вопросы
                      • Следующая тема

                      [ Script execution time: 0,0393 ]   [ 16 queries used ]   [ Generated: 12.06.23, 20:16 GMT ]  

                      В некоторых случаях при возникновении ошибок, во время отладки, компилятор показывает строчку дельфовых библиотек, где именно возникло исключение. Например обращение к несуществующему индексу массивов и прочих контейнеров, как здесь:

                        List1 := TList.Create;
                        List1.Add(P);
                        P := List1.Items[1];
                      

                      Получим указание на строку: Error(@SListIndexError, Index); в System.Classes

                      В больших многопоточных проектах отловить подобные ошибки через трассировку бывает крайне сложно, записывать лог после каждой строки — тоже не вариант. А хотелось бы знать строку своего проекта от куда это все началось. Как нибудь можно выявить искомую строку в режиме отладки?

                      Zam's user avatar

                      Zam

                      1873 серебряных знака12 бронзовых знаков

                      задан 28 мар 2017 в 21:02

                      HeathRow's user avatar

                      7

                      Для этого нужно:

                      1. Текущее состояние стека. В нем хранится последовательность вызовов функций/процедур (Call Stack), которая привела нас в место возникновения исключения, а также значения всех локальных переменных и входных параметров всех этих функций/процедур.
                      2. map-файл — информация о том по каким адресам в памяти расположены все наши глобальные переменные, функции/процедуры и их локальные переменные. Он генерируется компилятором.

                      На основании этих данных можно точно найти то что вам нужно.

                      Получить всю эту информацию в удобном виде можно либо в процессе отладки встроенным в delphi дебагером, либо с помощью компонентов типа EurekaLog, MadExcept, JclDebug и т.п. получать и сохранять в файл отчета об ошибках самой программой, работающей у клиента.

                      ответ дан 30 мар 2017 в 9:34

                      Герман Борисов's user avatar

                      Герман БорисовГерман Борисов

                      10.3k13 серебряных знаков37 бронзовых знаков

                      Типов сообщений компилятора — более двухсот. Рассмотрим перечень наиболее встречающихся сообщений класса Error

                      • 0. <Что-то1> expected but <Что-то2> found. Обычно это сообщение возникает при синтаксической ошибке.Например,в случае небаланса скобок,компилятор сообщит: ‘)’ expected but ‘;’ found (вместо ожидавшейся скобки найдена запятая).

                        Компилятор часто сообщает, что ‘end’ ожидается,например:x:= 5,7; здесь неуместен разделитель-запятая, а сообщается про end. (‘END’ expected but ‘,’ found)

                      • 1. <Имя> is not a type identifier. Данное <Имя> не является именем типа.
                      • 2. ‘;’ not allowed before ‘Else’. Перед else нельзя ставить точку с запятой
                      • 3. Abstract method must be virtual or dynamic. Абстрактный метод должен быть виртуальным или динамическим.
                      • 4. Ambiguous overloaded call to <Имя блока>. Компилятор не может однозначно выбрать перегружаемый блок. Измените параметр.
                      • 5. Array type required. Ошибка возникает в случаях, когда в индексе элемента массива указано больше уровней, чем предусмотрено описанием, и если массив не описан. Например, после объявления двумерного массива х или простой переменной х ошибочно записывают элемент х[2,1,1] (в нем показано три измерения).
                      • 6. Assignment to FOR-loop variable <Имя>. Присваивание значения параметру FOR-цикла в теле цикла.

                        Например, вследствие описки дважды используется имя i в кратном цикле:

                        For i:= 1 to n do For i:= 1 to m do ...
                        
                      • 7. Break or Continue outside of loop. Break или Continue — не в цикле.
                      • 8. Cannot initialize local variables. Локальные переменные запрещено инициализировать (задавать им значения при описании).
                      • 9. Cannot assign to/read a read-only/write-only property. Присвоение значения свойству read/only и чтение свойства write/only запрещены.
                      • 10. Constant expression expected.В этом месте должна стоять константа или константное выражение, например константа выбора в структуре Case.
                      • 11. Constant expression violates subrange bounds. Выход значения константы из диапазона. Контроль не полон. Например, «сойдет с рук» присваивание x:=3000000000, где х имеет тип integer, но начение х будет искажено.
                      • 12. Constant or type identifier expected. Требуется имя типа или тип-диапазон.
                      • 13. Could not compile used unit <Имя>. Компиляция присоединенного модуля <Имя> невозможна.
                      • 14. Data type too large. Тип определяет структуру размером более 2 Гбайт; это слишком много.
                      • 15. Declaration expected but <Что-то> found. Пропущено описание или оператор.
                      • 16. Declaration of <Имя> differs from previous declarations… Данный заголовок блока не соответствует упреждающему объявлению блока.
                      • 17. Default parameter <Имя> must be by-value or constant. Необязательный параметр (со значением по умолчанию) не должен вызываться по ссылке.
                      • 18. Expression expected. В этом месте программы должно стоять выражение.
                      • 19. Expression too complicated. Выражение излишне сложно для компиляции.
                      • 20. File type not allowed here. В этом месте или в этой роли файловую переменную нельзя использовать. Например, она не может быть формальным параметром-значением.
                      • 21. For loop control variable must be simple local variable. Параметр цикла должен быть простой локальной (описанной в этом же блоке) переменной.
                      • 22. For loop control variable must have ordinal type. Параметр цикла должен иметь порядковый тип.Вещественный тип запрещен.
                      • 23. Function needs result type. В заголовке функции надо указывать тип ее результата.
                      • 24. Identifier expected but <Что-то> found. В этом месте должно стоять имя. Например, пропущено имя функции после Function.
                      • 25. Identifier redeclared <Имя>.<Имя> описано повторно, но в пределах блока имя можно описать лишь раз. Проверьте, не обозначена ли локальная переменная тем же именем, что и формальный параметр блока.
                      • 26. Illegal character in input file <знак>. Запретный знак, например «русская» буква, либо вы оставили скобку }, убрав открывающую скобку {.
                      • 27. Illegal type in Read/Readln (Write/Writeln) statement. Элемент запрещенного типа в списке ввода/вывода.
                      • 28. Incompatible types <указание типов>. Несоответствие типов по присваиванию или типов операндов одной операции. Сообщение выдается и при неверном использовании структур. Например, z — запись, ошибочно записано присваивание z:= 0 (работать надо с полями записи).
                      • 29. Invalid function result type. Недопустимый тип результата функции.
                      • 30. Label already defined: <Метка>. <Метка> уже помечает другой оператор.
                      • 31. Left side cannot be assigned to. He может быть такой левой части в присваивании. Примеры: попытка присвоить значение файловой переменной, присвоение значения формальному параметру-константе.
                      • 32. Line too long. В строке программного текста больше 255 знаков.
                      • 33. Low bound exceeds high bound. Нижняя граница превышает верхнюю.
                      • 34. Missing operator or semicolon.Пропуск операции (например перед скобкой) или пропуск точки с запятой. При пропуске ‘;’ маркер ошибки стоит на очередном предложении (объявлении или операторе).
                      • 35. Missing parameter type. He указан тип формального параметра-значения или параметра процедурного типа.
                      • 36. Not enough actual parameters. He хватает фактических параметров.
                      • 37. Need to specify at least one dimension … Нужно задавать в операторе SetLength хотя бы один размер динамического массива.
                      • 38. Number of elements differs from declaration. Число элементов в структурной константе не соответствует ее описанию.
                      • 39. Operator not applicable to this operand type. Операция не применима к операндам данного типа. Например: ‘А’ or ‘В’; ‘Text1’* ‘Text2’.
                      • 40. Order of fields in record constant differs from declaration. Порядок полей в записи-константе не соответствует описанию записи.
                      • 41. Ordinal type required. Требуется порядковый тип (например, в индексе).
                      • 42. Out of memory. Компилятору не хватает памяти.
                      • 43. Statement expected but <Что-то> found. В этом месте должен стоять оператор. Сообщение выдается во всех случаях, когда в тело блока или секцию инициализации ошибочно помещают описание (<Что-то>). Ошибочная форма обращения к процедуре Procedure <Имя> или к функции Function <Имя> также вызывает сообщение.
                      • 44. Sets may have at most 256 elements. Множество (тип Set) не может содержать более 256 элементов.
                      • 45. Slice standard function only allowed as open array argument. Функцию Slice можно использовать лишь как фактический параметр
                      • 46. Statement not allowed in interface part. Предложения в секции интерфейса программного модуля недопустимы.
                      • 47. Syntax error in real number. Синтаксическая ошибка в записи числа вещственного типа.
                      • 48. There is no overload version of <Имя> that can be called with these arguments.Не предусмотрен перегружаемый блок <Имя>, который мог бы вызываться с таким аргументом. Пример: IntToStr(x), где х – выражение вещественного типа.
                      • 49. Too many actual parameters. Фактических параметров больше, чем формальных.
                      • 50. Type actual and formal var parameters must be identical. Тип фактического параметра должен быть идентичен типу формального параметра-переменной.
                      • 51. Type of expression must be <Тип>. Выражение должно быть указанного типа. Например,после While и Until должно стоять логическое выражение.
                      • 52. Undeclared identifier: <Имя>.Не описано <Имя>. Проверьте есть ли описание в нужном месте,нет ли описок в имени. Если указано имя компонента формы, проверьте,поместили ли компонент на данную форму.
                      • 53. Unexpected end of file in comment started on line <N>. Неожиданный конец файла при незавершенном комментарии, начало комментария — в строке N.
                      • 54. Unit name mismatch: <Имя>. Имя модуля ошибочно.
                      • 55. Unsatisfied forward or external declaration <Имя>. Отсутствует описание блока, объявление которого было дано (заголовок в интерфейсе или в описании объектного типа, либо упреждающее описание).
                      • 56. Unterminate string. He закрыта апострофом строка-константа типа string.

                      Рассмотрим также некоторые сообщения классов warning и hint.

                      • Return value of function <Имя> might be undefined. В теле функции нет присваивания ее результата.
                      • Variable <Имя> might not have been initialized. Указывает имя переменой, которой не задали значения.
                      • For-Loop variable <Имя> may be undefined after loop. Попытка использования значения параметра For-цикла после завершения этого цикла.
                      • Text after final ‘END.’ ignored by compiler. Текст, идущий за конечной строкой модуля, игнорируется компилятором.
                      • Variable <Имя> is declared but never used in <Имя блока>. Обращает внимание на переменную <Имя>, описанную,но не нашедшую применения.
                      • Value assigned to <Имя> never used. Хотя бы одно значение переменной <Имя> никак не использовано.

                      Несколько рекомендаций

                      Сосредотачивайтесь на первом сообщении компилятора. Исправление хотя бы одной ошибки и повторная компиляция может значительно уменьшить число сообщений об ошибках,поэтому не упорствуйте, стремясь понять сразу причину каждого сообщения.

                      Не удаляйте прежний вариант кода,пока не убедитесь,что ошибка устранена. Лучше на время закомментировать код,заключив его в скобки: { код }

                      Компилятор не анализирует, как будет выполняться программа, поэтому выход значения индекса из диапазона выявляет только если индекс задан константным выражением. Деление на ноль вообще пропускается, кроме оператора div, в случае если делитель — константное выражение.

                      0 / 0 / 0

                      Регистрация: 24.10.2009

                      Сообщений: 6

                      1

                      09.10.2013, 18:51. Показов 8470. Ответов 4


                      Студворк — интернет-сервис помощи студентам

                      Привет всем! Есть код на Delphi 7, программа парсит в инете выбирает информацию. Код довольно большой. Вопрос в следующем как сопоставить адрес ошибки Access violation at address 0048AEC4 in module … read of address 00000000, с конкретной строкой в программе? Теоретически понятно, что где то программа обращается например к элементу массива, за его пределами, но при этом программа не ломается а продолжает выполняться. Так как запросы в инет на получение данных, она шлет по таймеру. Отловить ошибку не представляется возможным, т.к. модуль может работать часами и не сбоить, а может вывалиться, через пару минут. Отсюда вопрос как сопоставить адрес 0048AEC4 с конкретной строкой кода. Если кто в теме откликнетесь, перечитал кучу советов, бьюсь уже кучу времени и отдачи нет. Заранее спасибо!!!



                      0



                      пофигист широкого профиля

                      4662 / 3096 / 855

                      Регистрация: 15.07.2013

                      Сообщений: 17,855

                      09.10.2013, 20:57

                      2

                      Запустить программу под отладчиком, поставив точку останова там, куда процесс обязательно попадет (например на нажатие какой-нибудь кнопки, если в программе есть хотя бы одна кнопка). Когда процесс остановится, открыть меню Делфи -> Search -> Goto Address. В окошко ввести адрес указанный в сообщении об ошибке ($0048AEC4). Ну а затем попытаться развернуть стек вызовов глядя в окошко Call Stack (Меню Делфи -> View -> Debug Windows -> Call Stack.

                      Если это для вас слишком сложно, то есть готовые средства. Например Эврика



                      2



                      Ivanjulai

                      0 / 0 / 0

                      Регистрация: 24.10.2009

                      Сообщений: 6

                      09.10.2013, 21:20

                       [ТС]

                      3

                      Спасибо! Да чего я и боялся случилось… Предложенным методом нашел, что ошибка возникает в строке:
                      Temp := Dispatch.GetIDsOfNames(GUID_NULL, NameRefs, NameCount,
                      GetThreadLocale, DispIDs);
                      Которая находится в следующей процедуре:

                      Delphi
                      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
                      
                      procedure GetIDsOfNames(const Dispatch: IDispatch; Names: PChar;
                        NameCount: Integer; DispIDs: PDispIDList);
                       
                        procedure RaiseNameException;
                        begin
                          raise EOleError.CreateResFmt(@SNoMethod, [Names]);
                        end;
                       
                      type
                        PNamesArray = ^TNamesArray;
                        TNamesArray = array[0..0] of PWideChar;
                      var
                        N, SrcLen, DestLen: Integer;
                        Src: PChar;
                        Dest: PWideChar;
                        NameRefs: PNamesArray;
                        StackTop: Pointer;
                        Temp: Integer;
                      begin
                        Src := Names;
                        N := 0;
                        asm
                          MOV  StackTop, ESP
                          MOV  EAX, NameCount
                          INC  EAX
                          SHL  EAX, 2  // sizeof pointer = 4
                          SUB  ESP, EAX
                          LEA  EAX, NameRefs
                          MOV  [EAX], ESP
                        end;
                        repeat
                          SrcLen := StrLen(Src);
                          DestLen := MultiByteToWideChar(0, 0, Src, SrcLen, nil, 0) + 1;
                          asm
                            MOV  EAX, DestLen
                            ADD  EAX, EAX
                            ADD  EAX, 3      // round up to 4 byte boundary
                            AND  EAX, not 3
                            SUB  ESP, EAX
                            LEA  EAX, Dest
                            MOV  [EAX], ESP
                          end;
                          if N = 0 then NameRefs[0] := Dest else NameRefs[NameCount - N] := Dest;
                          MultiByteToWideChar(0, 0, Src, SrcLen, Dest, DestLen);
                          Dest[DestLen-1] := #0;
                          Inc(Src, SrcLen+1);
                          Inc(N);
                        until N = NameCount;
                        Temp := Dispatch.GetIDsOfNames(GUID_NULL, NameRefs, NameCount,
                          GetThreadLocale, DispIDs);
                        if Temp = Integer(DISP_E_UNKNOWNNAME) then RaiseNameException else OleCheck(Temp);
                        asm
                          MOV  ESP, StackTop
                        end;
                      end;

                      Которая в свою очередь находится в ComObj.pas из soursertlcommon вот и приехали… Я так понимаю исправить это сложно… Самое странное, что ни к каким видимым ошибкам она не приводит, кроме того, что программа встает колом и если сказать ОК и стартануть программу снова, она продолжает работать…



                      0



                      пофигист широкого профиля

                      4662 / 3096 / 855

                      Регистрация: 15.07.2013

                      Сообщений: 17,855

                      09.10.2013, 21:58

                      4

                      Цитата
                      Сообщение от Ivanjulai
                      Посмотреть сообщение

                      Так как запросы в инет на получение данных, она шлет по таймеру

                      Вот кстати узкое место. Периодический процесс по таймеру с непредсказуемым временем окончания. Проверьте внимательно не может ли где что-то не успевать создаваться или уничтожаться? Или наоборот что-то уже уничтожено а к нему поступает задержавшееся обращение.



                      1



                      0 / 0 / 0

                      Регистрация: 24.10.2009

                      Сообщений: 6

                      10.10.2013, 18:42

                       [ТС]

                      5

                      Спасибо, ясно где собака порылась… Хотя вроде логика там верная, таймер запускается, через определенное время, по завершению события DocumentComplit… Ладно главное теперь знаю как найти место ошибки, чего и добивался, еще раз спасибо!!!



                      0



                      Понравилась статья? Поделить с друзьями:
                    • Как удалить программу если она установлена с ошибкой
                    • Как удалить программу если она выдает ошибку при удалении
                    • Как удалить программу в которой ошибка
                    • Как удалить файл с ошибкой чтения
                    • Как удалить приложение с ошибкой ps4