Почему '{' генерирует исключение NullReferenceException в статическом методе? - PullRequest
6 голосов
/ 26 августа 2010

Это своего рода эзотерика. Я столкнулся с NullReferenceException при попытке открыть форму (в конструкторе winforms) в проекте winforms в Visual Studio 2008. Трассировка стека указывает на четвертую строку следующего кода:

public static class Logger
{
    public static void LogMethodEnter()
    {
        var frame = new StackFrame(1);
        var method = frame.GetMethod();
        Trace.TraceInformation("{0}.{1}.{2}()", method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name);
        Trace.Indent();
    }

    public static void LogMethodExit()
    {
        Trace.Unindent();
    }
}

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

Почему это происходит и почему трассировка стека исключений указывает на строку с фигурной скобкой?

Уточнение: Исключение с нулевым указателем возникает только в конструкторе winforms. Когда приложение запускается, оно не выдает эту ошибку.

Ответы [ 5 ]

4 голосов
/ 26 августа 2010

Я предполагаю, что у вас есть инициализация статического члена где-то в вашем классе, и этот инициализатор выдает NullReferenceException.Кроме того, я полагаю, что у вас нет статического конструктора, поэтому ваш объект помечен как beforefieldinit, и поэтому NullReferenceException генерируется, в то время как ваш метод, использующий его, является JITed.

Что-то вроде:

public static class Logger
{
    private static object x = InitObjectX();
    private static object InitObjectX() {
        x.GetHashCode(); // Will throw since x is null.
    }

    public static void LogMethodEnter() 
    { 
        var frame = new StackFrame(1); 
        var method = frame.GetMethod(); 
        Trace.TraceInformation("{0}.{1}.{2}()", method.DeclaringType.Namespace, method.DeclaringType.Name, method.Name); 
        Trace.Indent(); 
    } 

    public static void LogMethodExit() 
    { 
        Trace.Unindent(); 
    } 
} 
4 голосов
/ 26 августа 2010

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

method.DeclaringType.Namespace

И причина, по которой вы можете увидетьИсключение NullReference вызвано тем, что выражение new StackFrame(1) парой предыдущих строк иногда может возвращать пустой кадр.Пустой фрейм означает, что вызов .GetMethod() вернет ноль, и вы идете.

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

3 голосов
/ 26 августа 2010

Возможно, файл .pdb , содержащий информацию о строке , устарел .

Чтобы это исправить, пересоберите проект и убедитесь, что создание файлов .pdb включено в настройках проекта. Для проектов C # это можно настроить на вкладке Build , установив для Advanced -> Debug Info значение full или только для pdb .

1 голос
/ 26 августа 2010

Я думаю, что проблема связана со статическим методом, вызываемым перед созданием статического объекта. Я исправил проблему в проекте winforms, добавив статический конструктор .

Если я правильно помню, статический конструктор блокирует весь объект во время выполнения.

0 голосов
/ 26 августа 2010

Указание на фигурные скобки / неправильная строка кода может когда-нибудь произойти.Я думаю, это просто, что исключение произошло в предыдущей строке кода, и Visual Studio по какой-то причине выделяет следующую строку.на любое количество внутренних и внешних факторов.

Извините, я не могу объяснить это очень хорошо.

...