Что может быть причиной NRE при закрытии формы?

При определенных обстоятельствах я получаю NRE при закрытии формы с помощью кнопки "Закрыть", которая просто вызывает собственный метод (WinForms) Close().

Определенные пути в коде работают нормально, но один конкретный путь вызывает исключение Null Reference. Поскольку это номинально сценарий, в котором на что-то ссылается что-то нулевое, как это может происходить, когда форма просто закрывается? Я могу представить, что, возможно, произошла утечка памяти, но что-то, на что я ссылаюсь, не понятно.

Какие возможные причины в коде могут быть?

ОБНОВИТЬ

Ответ Джону Скиту:

Я не могу отладить это обычным способом по скучным и трудоемким причинам (опять же), но я могу сделать следующее:

catch (Exception ex)
{
    MessageBox.Show(ex.Message);
    MessageBox.Show(ex.InnerException.ToString());
    SSCS.ExceptionHandler(ex, "frmEntry.saveDSD");
}

Последний является внутренним / пользовательским методом обработки исключений.

Все, что я получаю из этих строк:

"Null Reference Exception"
Nothing (empty string)
"Exception: NullReferenceException Location: frmEntry.btnSave.click

Обратите внимание, что последнее показанное исключение теперь подразумевает в качестве виновника btnSave.click, тогда как ранее он указывал пальцем на saveDSD. Любопытнее и любопытнее. Является ли это случаем эффекта Хоторна * в действии (хорошо, модифицированного эффекта Хоторна, в том смысле, что добавление этого кода отладки может изменить ситуацию).

  • Канонический эффект Хоторна больше похож на такой сценарий: кучка кошек играет в баскетбол. Некоторые девушки подходят и смотрят. Кошки начинают хвастаться и хот-дог, и один ломает ногу. Это вина девушек? Нет. Случилось бы это, если бы они не смотрели? Нет.

ОБНОВЛЕНИЕ 2

Разговор об эффекте Хоторна: Когда я скопировал два вызова MessageBox.Show() в блок catch файла frmEntry.btnSave.click, я получил:

"Null Reference Exception"
"Null Reference Exception"
"Exception: NullReferenceException Location: frmEntry.Closing"

IOW, местоположение NRE продолжает двигаться, как белка на проселочной дороге, когда [h,sh]e встречает две машины, идущие в противоположных направлениях.

ОБНОВЛЕНИЕ 3

И это произошло еще раз: добавление этих MessageBox.Show() к событию закрытия формы приводит к тому, что NRE появляется из другой дыры и объявляет себя. Этот инбредный код порождает (или клонирует) недоумки по счету, или так кажется.

ОБНОВЛЕНИЕ 4

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

Вот последний вопиющий хэдскретчер / ревуран:

int cancelled = ListRecords.cancelled;
if (cancelled == 0)
. . .

Общедоступному "отмененному" члену ListRecords (в ​​другом классе) присваиваются только значения 0 и 1. Таким образом, отмененный звук не только звучит как bool, он также действует как bool. Почему это не былообъявлено как bool?!?!?

Официальное изображение этой кодовой базы должно быть "The Scream" Эдварда Мунка.

ОБНОВЛЕНИЕ 5

Может быть, я высказываюсь, но недавний опыт побудил меня придумать новое имя для определенных типов кода и иллюстрацию для многих проектов. Код, который никуда не денется, а просто занимает место (назначения сделаны, но затем не выполняются или не вызываются пустые методы / обработчики). Теперь я называю "Winchester Mystery House code".

А что касается типичного проекта (я был "захваченным" сотрудником, а также подрядчиком по многим проектам сейчас, имея почти 20-летний опыт программирования), то теперь я сравниваю ситуацию с группой людей, валяющихся в зыбучих песках. Когда они нанимают новых людей, чтобы "подняться на борт", они действительно хотят, чтобы они прыгали с ними в зыбучие пески. Как это поможет? Это просто случай "несчастья любит компанию"? Что они должны делать, так это сказать: "Брось нам веревку!" не "Заходи, зыбучие пески в порядке!"

Во многих случаях это, вероятно, просто энтропия и "безопасность работы" во время игры; если они будут продолжать бороться с чудовищем, которое они выбрали или создали, то их с трудом завоеванные знания о том, как более или менее держать зверя в страхе, будут держать их на полудобной работе. Если они вносят какие-либо радикальные изменения (большинству команддействительно необходимо внести некоторые радикальные улучшения, IMO), это может поставить под угрозу их статус занятости. Возможно, ответ заключается в том, чтобы нанять / заключить контракт с "переходными командами", чтобы переместить команды / компании из доисторических клубов динозавров в 21 век, обучая "старую гвардию", чтобы они могли сохранить свою работу. В конце концов, этих "спасителей" недостаточно для того, чтобы в любом случае украсть старые руки - тренировать их, набирать скорость и двигаться дальше. Все выиграют. Но многие, похоже, предпочитают продолжать валяться в болоте или зыбучих песках.

Прежде чем кто-либо наймет программиста, он должен дать им как минимум тест, в котором прохождение теста подтвердит, что он, по крайней мере, знаком с основными принципами, изложенными в "Своде кода" Стива Макконнелла.

Хорошо, вернемся к борьбе с зыбучим песком...

ОБНОВЛЕНИЕ 6

Или: "Рефакторинг Spo-dee-o-dee":

"Поправка" с рефакторингом - это если вы измените имя переменной, например:

ChangeListType chgLst; // ChangeListType is an enum

...к этому:

ChangeListType changeListType;

... и если есть таблица данных со столбцом с именем "chgLst", операторы SQL также могут быть изменены, что может испортить, если не ваш день, хотя бы часть из них.

Другая потенциальная ошибка, когда вы получаете, подсказки "[имя переменной] только назначено, но его значение никогда не используется". Вы можете подумать, что можете просто кавалерно все это сделать, но остерегайтесь того, что любой связанный с ним код, который вы можете закомментировать вместе с назначениями для этих мертвых переменных, не дает надежных побочных эффектов. Следует признать, что это был бы плохой способ кодирования (побочные эффективные методы, хранящие их возвращаемые значения в переменных, которые игнорируются), но... это происходит, особенно когда первоначальный кодер был безумным ученым-ковбоем с головой пропеллера.

Этот код настолько переполнен анти-паттернами, что я не удивлюсь, если Батерик и / или Простота заключат контракт с этим парнем.

Если подумать, кроме архитектуры, дизайна, кодирования и форматирования этого проекта, это не так уж и плохо...

"Франкенштейн" Мэри Шелли действительно был очень предусмотрительным, но не таким, как думали большинство людей. Вместо общего предчувствия, связанного с технологией, которая выходит из-под контроля, она гораздо более конкретна, чем эта: она является предысторией большинства современных программных проектов, в которых "куски частей" отсюда и там сжимаются вместе, не обращая внимания на то, тазобедренная кость связана с бедренной костью " (или должна быть) и совпадают ли эти части или будут отклонять друг друга; левая рука не знает, что делает правая, а дьявол берет на себя самое заднее! И т.п.

1 ответ

Решение

Это может произойти в любой из следующих ситуаций:

  • объект является null и ваш код имеет obj.ToString()
  • элемент строки null и ваш код имеет item.Trim()
  • Настройки mySettings есть null и ваш код имеет mySettings.Path

Менее распространенными вещами будет поток, который отправляет информацию, или последовательный порт, который пытается получить данные после SerialDataReceivedEventHandler был удален.

Посмотрите, что делают код вашей подозрительной формы и код родительской формы во время закрытия этой подозрительной формы и какие другие процессы могут выполняться в подозрительной форме.

Другие вопросы по тегам