#.net #vb.net #debugging #stack-trace #line-numbers
#.net #vb.net #отладка #трассировка стека #номера строк
Вопрос:
Я хотел бы распечатать свое отладочное сообщение с номером строки в VB.net приложение. Мне понравилось это,
Dim st As StackTrace
Dim sf As StackFramee
st = New StackTrace(New StackFrame(True))
sf = st.GetFrame(0)
Console.WriteLine.("Line " amp; sf.GetFileLineNumber())
Я хочу поместить фрагмент в класс, каждый раз, когда я вызываю метод logMsg, чтобы зарегистрировать мое сообщение с номером строки в исходном коде.
Но я обнаружил, что если я помещаю приведенный выше фрагмент в класс, номер строки всегда остается неизменным, это строка, для которой я добавляю ‘st’.
Функция точно такая же с макросом _LINE в C . На самом деле я программист на C .
В любом случае, чтобы исправить эту проблему? Спасибо.
Ответ №1:
Показанный вами код работает точно так, как ожидалось. Это печать номера строки, в которой вы захватили фрейм стека. Поскольку вы определили его в другом классе, он печатает номер строки файла, который содержит этот класс.
Здесь важен GetFrame
метод. Фреймы стека нумеруются начиная с 0, который является последним загруженным фреймом стека. Итак, ссылаясь на кадр 0, вы даете указание среде выполнения напечатать номер строки последнего переданного кадра стека. Когда один метод вызывает другой, создается новый фрейм стека.
Вместо этого вам нужно изменить свой метод несколькими важными способами. Во-первых, вам нужно получить первый фрейм, который был помещен в стек. И, во-вторых, вы, вероятно, захотите принять параметр, содержащий информацию об исключении, на которое вы реагируете. Попробуйте переписать свой метод отладки, чтобы он выглядел примерно так:
Public Sub PrintCurrentLine(ByVal ex As Exception)
Dim st As StackTrace = New StackTrace(ex)
Dim sf As StackFrame = st.GetFrame(st.FrameCount - 1)
Console.WriteLine("Line " amp; sf.GetFileLineNumber())
End Sub
Также помните, что если вы выполняете код с включенной оптимизацией, такие вещи, как номера строк, могли измениться. Вам всегда нужно включать файл PDB в свой код, который содержит отладочную информацию, которая используется в подобных ситуациях. Он отображает оптимизированный код обратно в ваш исходный код.
Комментарии:
1. большое спасибо. В моем случае у меня есть класс для ведения журнала сообщений, которые записываются в файл. Вот почему я должен вставить информацию о номере строки в класс. Таким образом, это не способ записать номер строки в другой класс, верно?
2. @heefan: Ну, есть. Вы могли бы обойти весь стек, ища отдельный фрейм, который вы хотите. Как я упоминал выше,
GetFrame
метод является ключевым, потому что это то, что позволяет вам это делать. Как только вы определите правильный фрейм,GetFileLineNumber
будет делать именно то, что вы хотите (за исключением, конечно, режима выпуска без доступной отладочной информации). Хитрость заключается в получении правильного фрейма стека, поскольку вы вызываете другой метод для обработки отладки. Важно помнить, что каждый вызов метода создает новый фрейм стека.3. Да, вы правы. Ключевая проблема заключается в том, что когда приложение вычисляет фрейм, это GetFrame. Спасибо за ваше руководство.
4. @heefan: Я, честно говоря, не уверен, чем это отличается от C . Разве у вас не было бы такой же проблемы при использовании
_LINE
макроса? Если вы вызываете метод в другом исходном файле, у него будет другой номер строки. Вы должны найти правильный фрейм в стеке, чтобы получить правильный номер строки. В любом случае, пожалуйста.5.@спасибо, Коди. В C это довольно полезно и намного проще, чем VB.net . Мы можем получить номер строки сообщения отладки и быстро их найти, особенно во встроенной среде Linux, используя СТРОКУ ФАЙЛ и ФУНКЦИЮ. В настоящее время я использую систему в своем другом проекте. Кстати, существует система ведения журнала с открытым исходным кодом под названием log4cpp. В любом случае, большое спасибо.
Ответ №2:
После прочтения нескольких ответов я пришел к следующему решению, эквивалентному СТРОКЕ макроса C
(New StackTrace(New StackFrame(True))).GetFrame(0).GetFileLineNumber())
который можно использовать, например, как:
Console.WriteLine(String.Format("Executed on line# {0}", (New StackTrace(New StackFrame(True))).GetFrame(0).GetFileLineNumber()))
Ответ №3:
Скомпилированные сборки не будут иметь номеров строк, связанных с ними. Это не информация, которая является частью сборок.
Информация хранится в файле символов отладки — pdb
файле.
Из MSDN — класса StackTrace:
Информация о трассировке стека будет наиболее информативной при отладке конфигураций сборки. По умолчанию отладочные сборки включают символы отладки, в то время как релизные сборки этого не делают. Символы отладки содержат большую часть информации о файле, имени метода, номере строки и столбце, используемых при создании объектов StackFrame и StackTrace.