2016-09-29 6 views
4

У меня возникли проблемы с пониманием трассировки стека в .net 4. Я получаю разные номера строк для идентичного кода, запущенного в приложении консоли или веб-службе, размещенной в IIS 7.5 (оба используют .net 4). ПрименениеНеверный номер строки трассировки строки внутри блока foreach

консоли:

static void Main(string[] args) 
{ 
    try 
    { 
     var test = new List<int>() { 1, 2, 3 }; 
     foreach (var root in test) 
     { 
      throw new Exception("foobar"); 
     } 
    } 
    catch(Exception e) 
    { 
     throw; 
    } 
} 

При проверке трассировки стека номер строки «е» внутри поймать блока, я получаю «8», которая является то, что я освобожденный (линию броска нового Exception ("Foobar"))

веб-сервис

[WebMethod] 
public void Test() 
{ 
    try 
    { 
     var test = new List<int>() { 1, 2, 3 }; 
     foreach (var root in test) 
     { 
      throw new Exception("foobar"); 
     } 
    } 
    catch (Exception e) 
    { 
     throw; 
    } 
} 

В этом случае ситуация становится странной - при проверке номера строки трассировки стека я получаю «7», , который является началом foreach блок. То же самое происходит с классическим для, но если заявление, например, работает ОК.

Любые идеи?

EDIT:

Что касается ответа от машины Узнав о несоосности язя или исполняемой линии и PDB. Если я добавлю лишние строки перед исключением, а некоторые после этого, я все равно получаю подобное поведение. Пример:

[WebMethod] 
public string Test() 
{ 
    try 
    { 
     var test = new List<int>() { 1, 2, 3 }; 

     var a = 1; 
     var b = 2; 
     var c = 3; 

     foreach (var root in test) 
     { 
      var d = 4; 
      var e = 5; 
      var f = 6; 
      throw new Exception("foobar" + (new System.Diagnostics.StackFrame(0, true)).GetFileLineNumber()); 
      var g = 7; 
     } 
     return null; 
    } 
    catch (Exception e) 
    { 
     return e.Message + e.StackTrace; 
    } 
} 

Здесь e.StackTrace отчеты линии "12" (foreach линия) и e.Message отчеты линии "17", который является правильным.

ответ

1

Это результат того, как исключения обрабатываются в Windows. Повторное исключение, исключенное одним и тем же методом, означает, что вы теряете информацию об исходном исключении, потому что исключения - это методы, ограниченные [1]. К сожалению, .NET унаследовала это ограничение, поскольку единственной альтернативой было внедрение исключений, не полагающихся на существующую инфраструктуру.

Если я правильно помню, это исправлено в 64-битном коде - убедитесь, что консольное приложение работает как 64-разрядное, и оно должно работать как ожидалось. Скорее всего, это причина того, что все работает отлично в тестовом приложении, но не на вашем IIS (где код, скорее всего, работает как 32-битный, и, возможно, с debug=false). EDIT: На самом деле это не так. В то время как битность задействована, она, скорее всего, связана с оптимизацией JITters - foreach на 64-битной основе сообщает об исключении на линии foreach, заменяя foreach на using, GetEnumerator и т. Д. Или изменяя бит до 32 -бит сообщит об исключении при ретроне.

Если вы хотите избежать этой проблемы во всем коде, убедитесь, что вы никогда не отказываетесь от исключений, которые были первоначально выбраны одним и тем же методом. Извлечение throw new ... в отдельный метод (и обеспечение его не встроенного, что происходит автоматически, когда есть throw в текущем времени выполнения AFAIK MS) должно работать нормально. Не забывайте, что a foreach также содержит неявный using, то есть a finally.

[1] Излишне говорить, что это немного упрощает. Основная (собственная) структурированная обработка исключений содержит только одно исключение в кадре стека - она ​​не может отслеживать как исходный бросок, так и повторный бросок. Вы найдете много информации о том, как SEH работает с простым поиском Google, если вам интересно идти глубже :)

+0

При проверке части EDIT не происходит реорганизации. Его единственный блок try/catch и исключение в catch имеют номер строки для блока вместо строки внутри цикла. В IIS я работаю на 64-битной (для параметра «Включить 32-разрядные приложения установлено значение false»). Тем не менее - я попытался запустить его непосредственно из VS, поскольку предлагалось машинное обучение, и оно работает правильно! Так выглядит, что это связано с IIS. –

+0

UPDATE - Я устанавливаю для 32-битных приложений значение true, и теперь номера строк верны! –

+0

@PavleGartner Ну, это интересно. Ваш код консоли также разбивается на 64-битный? Убедитесь, что вы * не * присоедините отладчик, который отключает многие из оптимизаций, которые могут вызвать проблему. – Luaan

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

  • Нет связанных вопросов^_^