Как отладить непоследовательную нулевую ссылку в C #? - PullRequest
0 голосов
/ 24 февраля 2009

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

Каждый класс Animal имеет свой собственный класс регистратора для записи данных для каждого "временного шага" в симуляции. Таким образом, каждый Animal имеет свой собственный файл журнала. Он работал нормально всегда (3 года), пока мы не попытались запустить его на виртуальной машине. Тогда по какой-либо причине время от времени ссылка на регистратор будет нулевой для «временного шага», а затем в следующий раз она будет там. Действительно странная часть - StreamWriter внутри регистратора, кажется, никогда не теряет местонахождение своего файла. Это просто пропускает запись строки для этого временного шага. И журнал ошибок показывает NullReferenceException в классе Logger.

Я не могу найти шаблон для этого поведения. Класс Animal не был уничтожен и воссоздан. Регистратор создается в конструкторе Animal и уничтожается в IDispose. Любые идеи о том, как я бы начал отлаживать эту проблему?

Редактировать: Я могу воссоздать это будет только 3 животных, поэтому не должно быть 500 открытых файлов. Но спасибо за попытку.

Редактировать: Я не уверен, что я должен делать, когда улавливаю ошибку для Null Exception. Я его уже ловил, но не могу понять, как выяснить, почему это происходит. Извините за кажущиеся тупыми. Кроме того, я попробовал Thread.Sleep (300) для 10000 циклов, чтобы увидеть, происходит ли какая-то гонка, о которой я не знал. Он никогда не становился не нулевым в цикле. Но через 3 секунды, когда я перебрал двух других животных и вернулся, он больше не был нулевым.

Ответы [ 5 ]

5 голосов
/ 24 февраля 2009

Я бы сделал следующее.

  1. Настройка VS для запуска вашей программы под отладчиком
  2. Включить исключения первого шанса для исключения с нулевым эталоном
  3. Отладчик -> Исключения -> Развернуть Common Language Runtime -> Проверка, выданная для System.NullReferenceException
  4. Запустить программу
  5. Подождите

Если для воспроизведения потребуется много времени, я бы запустил его и ушел домой на ночь. Он будет ждать тебя утром;)

2 голосов
/ 24 февраля 2009

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

РЕДАКТИРОВАТЬ: Если это не условие гонки, мои секундные предположения могут заключаться в том, что, возможно, виртуальной машине не нравится, когда одновременно открываются 500 файлов ... Вы изучили это?

0 голосов
/ 25 февраля 2009

Это может быть что-то, связанное с ВМ ... Я видел похожие проблемы с памятью в VMWare с нативными приложениями на С ++, когда ни с того ни с сего запутывается память, и ИТ-специалисты говорят, что они ничего не делают с ВМ ... (и мы все знаем, что это значит, что они что-то делали с ВМ)

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

Но в любом случае, если он воспроизводится только на виртуальной машине, я бы попытался изолировать его на виртуальном сервере dev самостоятельно, используя выделенные ресурсы (без совместного использования, дробных процессоров или чего-либо еще) и посмотреть, сможете ли вы воспроизвести его. Затем перейдите оттуда ... к повторному добавлению среды того же типа, пока вы не сможете воспроизвести ее.

0 голосов
/ 24 февраля 2009

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

Найти, где назначается нулевая переменная. От чего бы он ни брал данные, он иногда дает ноль, верно?

Так что проверьте прямо сейчас, если он возвращает ноль, спите около 300 мс, затем повторите попытку, пока он не станет ненулевым.

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

0 голосов
/ 24 февраля 2009

Есть ли вероятность того, что у вас возникнут проблемы с многопоточностью, возможно, связанные с отложенной инициализацией?

...