2009-09-10 3 views
1

При чтении this recent question об необработанном XmlException я попытался воспроизвести его в консольном приложении .NET 2.0 и 3.5.Странное необработанное поведение XmlException

Однако в моем коде он ведет себя точно так, как ожидалось, метод XmlDocument.Load генерирует исключение XmlException, потому что исходный XML-файл содержит символ NULL.

Итак, почему оператор Load в следующем коде (из этого примера) не выбрал исключение XmlException? Более того, почему XmlException не обрабатывается действительным блоком try, окружающим вызов метода SelectNodes()?

Хотя я догадываюсь, что внутри может быть какая-то ленивая загрузка/кеширование, не такое поведение очень неинтуитивное и запутанное?

(Ранее вопрос ясно показывает скриншот отладчика жалуясь, что SelectNodes() бросил в XmlException, но что это необработанное ???)

XmlDocument xDoc = new XmlDocument(); 
    xDoc.Load(File.FullName); 

    //work through each print batch in this queue file 
    try 
    { 
     // This line throws an XmlException but is not handled by the catch! 
     XmlNodeList nodeList = xDoc.SelectNodes("Reports/PrintBatch"); 

     foreach (XmlNode printBatch in nodeList)//xDoc.SelectNodes("Reports/PrintBatch")) 
     { 
      PrintBatch batch = new PrintBatch(); 
      batch.LoadBatch(printBatch, File.Extension); 
      this.AddBatch(batch); 
     } 
    } 
    catch (XmlException e) 
    { 
     //this report had an error loading! 
     Console.WriteLine(e.Message); 
    } 

ответ

2

Исключение всегда выбрано XmlDocument.Load, как ожидалось.

Это просто, что иногда отладчик получает номер строки неправильно. По моему опыту, следующая строка кода, некорректно выделяемая как метатор исключения, не является чем-то необычным.

Вы можете видеть это на скриншотах: страница с ошибкой ASP правильно показывает, что XmlDocument.Load - это метатель, а не оператор SelectNodes.

+0

Вы выглядите правильно. Я проверил реализацию Load и SelectNodes в Reflector, и он появляется только Load вызывает XmlLoader.LoadNode() (как показано в трассировке стека). Поэтому символы отладки могут быть не синхронизированы с показанным кодом. – Ash

1

Там может быть много причин, почему вы получите исключение в то время как он этого не делает, что, скорее всего, связано с расположением символа NULL. Согласно его стеку, его нулевой символ, похоже, находится в конце XML, в позиции 115227. Возможно, текст перед ним является просто корректным XML и что дополнительный символ NULL был добавлен в конец файла случайно , Где у вас есть символ NULL?

Или его символ NULL находится внутри атрибута или элемента и считается частью текста. Это может также зависеть от того, что XML является UTF-8, UTF-16 или другим типом кодирования. Слишком много переменных для рассмотрения.


Когда символ NULL находится на конце, весь файл просто является красивой строкой с нулевым завершением. Тем не менее, как вы говорите, это странно, что это считается необработанным исключением, когда он находится внутри блока try-except ...

Есть некоторые interesting reading here об обнаружении необработанных исключений, но это не объясняет, почему они происходят.

Но если я должен угадать ... За классом XML есть куча неуправляемого кода. Из-за символа NULL этот неуправляемый код запутывается и создает ошибку при его выпуске. Вызов SelectNodes() вызовет проверку, и он обнаружит ошибку, поэтому она поднята. Система начинает обрабатывать обработчик исключений, но сначала пытается освободить xDoc, поскольку она не используется внутри или после блока исключений. Это освобождает неуправляемый код, но неуправляемый код все еще запутан, поэтому он снова создает исключение. Это предотвратит Catch для обработки исключения. Вы можете проверить это, добавив второй xDoc.Load() после оператора Catch, что предотвратит освобождение xDoc до Catch.

Тем не менее, это всего лишь предположение ... Кажется, .NET-ошибка для меня.

+0

Протестировано, что в файле 120K. NULL внутри XML-бросков, NULL в конце документа не вызывает никаких проблем в Load() или SelectNodes().Но реальный вопрос в том, почему XmlException считается необработанным, когда SelectNodes() вызывается ** внутри ** блока try, который явно обрабатывает XmlException? – Ash

Смежные вопросы