Как я могу узнать, какие исключения функция Delphi могла бы выдать?

Что такое NullPointerException?

Хорошим местом для начала является JavaDocs . Они охватывают это:

Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  • Вызов метода экземпляра нулевого объекта.
  • Доступ или изменение поля нулевого объекта.
  • Выполнение длины null, как если бы это был массив.
  • Доступ или изменение слотов с нулевым значением, как если бы это был массив.
  • Бросать нуль, как если бы это было значение Throwable.

Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.

blockquote>

Также, если вы попытаетесь использовать нулевую ссылку с synchronized, который также выдаст это исключение, за JLS :

SynchronizedStatement:
    synchronized ( Expression ) Block
  • В противном случае, если значение выражения равно null, NullPointerException.
blockquote>

Как это исправить?

Итак, у вас есть NullPointerException. Как вы это исправите? Возьмем простой пример, который выдает NullPointerException:

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }
}

Идентифицирует нулевые значения

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

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

Здесь мы видим, что исключение выбрано в строке 13 (в методе printString). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, что s имеет значение null, а вызов метода length на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когда s.length() удаляется из метода.

Трассировка, где эти значения взяты из

Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что s передается с printString(name) в методе print(), а this.name - null.

Трассировка, где эти значения должны быть установлены

Где установлен this.name? В методе setName(String). С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. ​​

Этого достаточно, чтобы дать нам решение: добавить вызов printer.setName() перед вызовом printer.print().

Другие исправления

Переменная может иметь значение по умолчанию setName может помешать ему установить значение null):

private String name = "";

Либо метод print, либо printString может проверить значение null например:

printString((name == null) ? "" : name);

Или вы можете создать класс, чтобы name всегда имел ненулевое значение :

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }
}

См. также:

Я все еще не могу найти проблему

Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).

12
задан Rob Kennedy 10 November 2010 в 23:10
поделиться

9 ответов

(Редактирование: теперь очевидно, что вопрос относился только ко времени проектирования, проверяя.)

Новый ответ:

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

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

, Почему? , поскольку основной цикл сообщения в TApplication. Выполненный () обертывает весь HandleMessage () вызовы в блоке обработки исключений, который ловит все типы исключительной ситуации. Таким образом у Вас будет неявная/по умолчанию обработка исключений приблизительно 99,999% кода в большинстве приложений. И в большинстве приложений, эта обработка исключений составит приблизительно 100% Вашего собственного кода - 0,001% кода, который не обертывается в обработку исключений, будет автоматически сгенерированный код.

, Если бы был инструмент, доступный для проверки этого на Вас, необходимо было бы переписать Application.run () таким образом, что он не включает обработку исключений.

(Предыдущий ответ: Приложение. Обработчик событий OnException может быть присвоен для ловли всех исключений, которые не обработаны другими обработчиками исключений. Пока это - время выполнения, и таким образом возможно, не точно, что Вы, после (оно походит, Вы хотите определить их во время проектирования), оно позволяет Вам захватывать любое исключение, не обработанное в другом месте. В сочетании с инструментами, такими как материал JCLDebug в Библиотека Кода джедая , Вы могли зарегистрировать отслеживание стека для обнаружения где & почему исключение произошло, который будет допускать дальнейшее расследование и добавление определенной обработки исключений или предотвращения вокруг виновного кода... )

12
ответ дан 2 December 2019 в 03:19
поделиться

Мое предположение - то, что Вы пытаетесь заставить Delphi вести себя как Java, который не является хорошим подходом. Я советовал бы для не волнения слишком много о необработанных исключениях. В худшем случае они будут пузыриться до универсального обработчика исключений VCL и вызывать диалоговое окно сообщения Windows. В нормальном приложении они не остановят приложение.

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

11
ответ дан 2 December 2019 в 03:19
поделиться

За исключением сканирования на ключевом слове "повышения", нет никакой конструкции языка в Delphi, который говорит случайному читателю, какие исключения могут ожидаться от метода.

Во времени выполнения, можно было добавить всеобъемлющий обработчик исключений в каждом методе, но это не желательно, поскольку это замедлит скорость выполнения. (И это является громоздким, чтобы сделать также).

Добавление блока обработки исключений к методу добавит несколько инструкций по сборке к нему (даже когда исключение не инициировано), который формирует измеримое замедление, когда метод называют очень часто.

Там существуют несколько библиотек, которые могут помочь Вам в анализе исключений на этапе выполнения, как madExcept, JclDebug, и EurekaLog. Эти инструменты могут зарегистрировать все виды деталей об исключении, очень желательно использовать одного из тех!

5
ответ дан 2 December 2019 в 03:19
поделиться

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

Одной фундаментальной вещью о Delphi являются исключения, являются иерархическими: Все определенные исключения языка убывают от Исключение , хотя стоит отметить, что на самом деле возможно повысить любой потомок TObject.

, Если Вы хотите к [1 112] выгода каждое исключение, которое повышено в конкретной процедуре, просто оберните ее в попытка / кроме [1 113] блок, но как был упомянут , это не рекомендуется .

// Other code . . . 
try
  SomeProcedure()
except  // BAD IDEA!
  ShowMessage('I caught them all!');
end;

, Который поймает все, даже экземпляры повышенного TObject. Хотя я утверждал бы, что это редко - лучший план действий. Обычно Вы хотите использовать попытка / наконец блок и затем позволить Вашему глобальному обработчику исключений (или один финал попытка / кроме [1 116] блок) на самом деле обрабатывать исключения.

5
ответ дан 2 December 2019 в 03:19
поделиться

Я буду второй (или это треть) MadExcept. Я использовал его успешно в нескольких коммерческом применении без любых проблем. Хорошая вещь о MadExcept состоит в том, что он генерирует отчет для Вас с полным отслеживанием стека, которое будет обычно указывать на Вас в правильном направлении относительно того, что пошло не так, как надо и может даже включать снимок экрана, также имеет, послали это по электронной почте автоматически Вам от клиентского компьютера с простым щелчком мыши.

Однако Вы не хотите использовать это для ВСЕХ исключений, только для ловли тех Вы отсутствуете. Например, при открытии базы данных и сбоев входа в систему для Вас было бы лучше поймать и обработать этого самих, а не дать пользователю, ошибка значения по умолчанию MadExcept в Вашем приложении произошла сообщение.

4
ответ дан 2 December 2019 в 03:19
поделиться

Любое исключение не явно или обычно обрабатываемый на определенном уровне будет сочиться вверх в стеке вызовов. RTL Delphi (Библиотека Времени выполнения) генерирует ряд различных классов исключений - (математические ошибки, ошибки доступа, класс определенные ошибки и т.д.). Вы можете, принял решение обработать их конкретно или обычно в другой попытке кроме блоков.

Вы не должны действительно объявлять новые классы исключений, если Вы не должны распространять определенный функциональный контекст за исключением.

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

редактирование: Это - всеохватывающее страхование против необработанных исключений

try
  ThisFunctionMayFail;
except
  // but it sure won't crash the application
  on e:exception
  do begin
    // something sensible to handle the error 
    // or perhaps log and/or display the the generic e.description message
  end
end;
4
ответ дан 2 December 2019 в 03:19
поделиться
3
ответ дан 2 December 2019 в 03:19
поделиться

Как Jim McKeeth указывает, Вы не можете получить категорический ответ, но мне кажется, что каждый мог частично , отвечают на вопрос некоторым статическим анализом: учитывая конкретную функцию/процедуру, создайте граф вызовов. Проверьте каждую из функций в том графе вызовов для оператора повышения. Это сказало бы Вам, например, тому TIdTcpClient. ReadString может повысить EIdNotConnected (среди других).

А умный анализатор мог бы также отметить, что некоторый код использует / оператор, и включайте EDivByZero как возможность, или что некоторая процедура получает доступ к массиву, и включайте ERangeError.

, Что ответ, немного более трудный, чем простой захват для "повышения".

1
ответ дан 2 December 2019 в 03:19
поделиться

Для попытки во время выполнения Eurekalog. Я не знаю, существует ли инструмент в течение времени проектирования. У Вас будет больше dificoulties, даже когда Вы сделали, чтобы третье лицо кодировало без источника. Нет никакой потребности в Delphi для ловли исключений, таким образом, Вы не должны объявлять их как в Java.

то, Что я хотел сказать, - то, что Delphi не требует, чтобы исключение было обработано. Это только завершит программу. EurekaLog обеспечивает средства зарегистрировать обработанные и необработанные исключения и обеспечить богатство информации о насыщении программы, когда исключение произошло, включая строку кода он произошел в и стек вызовов в то время.

1
ответ дан 2 December 2019 в 03:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: