Wednesday, February 4, 2026

Debugging Tips and Tricks Part 1

>> If your code is perfect and
there's nothing wrong with it,
don't watch this episode
of Visual Studio Toolbox
where Leslie Richardson will show
us debugger tips and tricks.
>> I envy that person.
[MUSIC]
>> Hi, welcome to
Visual Studio Toolbox.
So I'm your host
Robert Green and joining me
today is Leslie
Richardson. Hey, Leslie.
>> Hi.
>> Thanks for coming on the show.
>> Thanks for having me.
>> Leslie is a PM in
Visual Studio land.
>> Sure, I am.
>> We're going to talk about
debugging tips and tricks.
>> Yes, we are. So there's
obviously a lot to
cover in the debugging space
that sadly a lot of
people don't know about.
You can spend countless hours
debugging that one bug
and going through
the most tedious steps
possible when at the end of
the day you just want to get
back to writing code, right?
>> Yeah.
>> Yeah, so hopefully some
of these tips that I show
you will help you
out in the long-run.
>> Cool, and a lot of these have
been in the product for a while.
Some are new to 2019.
>> Yup.
>> So if you can remember
too when there's
something that's brand new and
2019, let's call that out.
>> Okay.
>> Otherwise, this is just
stuff in Visual Studio.
>> Awesome. Yeah, definitely.
So I'm going to be focusing more
on the .NET space today but
a lot of these features
overlap into C++ as well.
So I'm in Visual Studio
2019 right now
and I'm using an ASP.NET
Core application.
Because I loved to read so much,
this is an app that randomly gives
me a list of books that
I can choose to read and
add to my shelf or reject and
they won't be added to my shelf.
So this app also has a lot
of problems with it,
so hopefully we can use some of
the debugging tools available to
us in order to figure them out.
>> Cool.
>> So first off, I have
a breakpoint already set in
this Book Manager constructor
here and this happens
pretty early on in my program's
execution where it takes in
a JSON file containing a bunch
of different book-related
information,
converts each piece of that into
a book object and then stores
each of those in a list.
So I'm at the start
of my function here
but I actually want to navigate
to the bottom here instead.
So normally that
would be when I start
stemming F10 or step over in order
to get down there but that can
be tiresome especially because
I have this for loop
right in the middle,
so that can take a lot of
time and that's not
very productive of me.
So the other option
of course is to just
set a breakpoint at
the end and then hit F5.
But then if I do that,
I have to remember to delete
the breakpoint afterward.
>> Right, because
the next time you run
the app and you get up and go
for a coffee or something,
you come back and sitting on that
breakpoint you forgot to remove.
>> Exactly, it's like I
thought it was going to run
without me while I
get my coffee but no.
So another alternative is
something called Run to Click
which I can perform by
hovering over the line I
want to navigate to next.
When I do that, you'll notice there's
this little green glyph
icon that shows up,
and I can click on that and it'll
run all of my code up to
that particular line.
>> Which is easier
than going down there
right-clicking and
then finding Run to,
or set next statement,
or whatever it was.
This is just quicker.
>> Exactly. It's like having
a remote control for
your code and being
able to fast-forward to
where you want to go.
So from there, the reason
why I wanted to go
to the end of this function
is because I wanted to hone
in on that book lists which stores
a hundred different books
because I want
to quickly inspect each one.
When I hover over
it, I get a data tip
but one of my problems that I have
a data tips from time to time is
that the moment I hover away
from it, it disappears.
So if I want to keep
it for a while longer,
what I can do instead is pin it,
and when I pin it,
this data tip will stick around
for as long as I decided to leave
it until I ultimately close it.
>> You can drag that to
a second monitor; is that true?
>> You know I haven't actually tried.
Good question. I feel like
that should be possible.
>> Okay.
>> But good question. The good news
about this is that when I close
out of my debugging session here,
it'll still be present even
when I start a new one.
So now if I wanted to inspect
all of the contents
of this list here,
at first glance, this
isn't really helpful.
Let's say I wanted to inspect
each book by their names,
it would be a little
tedious to expand each
of these out until I find there's
the title property and
then keep going to
the next one and so forth
until I find what I'm needing.
So this also goes for if I were in
the Locals window as
well or Watch, or Autos.
Ideally, it would be
a lot nicer if instead of
getting the type of object
under the Value column,
I could see particular
properties that I'm
interested in so I can just
quickly skim through this list.
So thankfully, there is
a feature that you can
use in Visual Studio,
that's one of my favorites and
it's an attribute
called DebuggerDisplay.
That is an attribute
that allows you to
customize how you view
your objects in the Watch,
Autos, Locals, and Data Tip windows.
So to do that, I can go and
see where I defined my class.
At the top of that class definition,
I can write in
some DebuggerDisplay syntax.
The curly brackets
will return the value
of any property or properties
because I can go plural with it,
I can also use expressions,
if I wanted of whatever
property that I specify.
In this case, I want to view
books by their title property.
So I'm going to type in title,
and I'm also going to have to
restart the debugging session.
But hopefully, this is
where the magic happens.
So this is an attribute that
exists currently in F#,
C#, and Visual Basic.
So this is for manage users
but if you're a C++ user,
the equivalent that you
can use that performs
the same function is
something called Natvis
where the difference
mainly is that you have
to create a separate Natvis file
inside your project.
That contains some XML that
you can add to or modify in
order to perform the thing
that I'm about to show you.
So I need to go back to the end
of this function again.
I'm going to use Run To Click,
and I have my Data Tip that I penned
earlier that's still here
because I never closed it.
This is my favorite.
This is the magic.
>> That is cool.
>> So cool. I love it a lot.
>> Okay, now this is the
part where we have fun.
How long it's been in the process?
>> Yeah. Longer than 2015.
Longer than 2015. It's
been around for a while.
Longer than me, definitely.
>> That's my favorite
part of the show.
>> I get asked that all the time.
So is this a 2017, 2019 exclusive?
I'm like, "Oh no".
>> No. Awesome.
>> Yeah. So that's
one of my favorites.
So another thing that I like-
>> You can do
expressions, so you could
concatenate a couple
of fields, actually?
>> Exactly, yeah. If you wanted to do
some simple type of expressions,
then you can do that as well.
If you're interested in seeing
one property plus
another it's possible.
>> Could you do something
like a function that
says if these three
fields are missing,
just display "incomplete",
then if they're there,
display "complete". Can
you do stuff like that?
>> You can, yeah. You can do some
simple if conditional
type statements as well.
Do it at your own risk.
My recommendation for
when things start to
get very complicated in
your DebuggerDisplay syntax,
is to create another property
or function within
that class first called like
the DebuggerDisplay or
something like that.
Include all that logic and then you
can write the function name inside-
>> That makes a lot of sense.
>> -the DebuggerDisplay.
>> Okay.
>> From there,
another feature that I like
are the Text Visualizers
in Visual Studios.
So for instance, I have
this JSON variable here that
stores all my JSON contents,
and if I'm looking at it, first,
I need to actually
navigate back to it
because this is earlier on in
my code and I'm
currently out of scope.
So what I can use for
that is something
called set to .NET statement which
I think you mentioned earlier.
So to do that, I can pretend as
if I were doing another Run To Click,
so I can hold down
the Control key and that
green glyph will turn into
yellow icon which will
automatically move
my execution pointer up
to that particular line.
So that's nice especially if you want
to try out what different
execution paths are going to be
looking like or if you
want to go back and
re-inspect a previous variable
but you have to use it at
your own risk because
since you are changing
the execution flow in a way that
it is not necessarily intended,
it has the potential to mess
with the rest of your codes
execution unless you restart and
make a new debugging session.
So from there, I have the JSON
variable and looking at it,
it's not very readable right off
the bat because it's formatted
for JSON particular.
That and it cuts off the screen.
So if I'm looking at it in
the Local's window for instance,
there's this magnifying glass icon
that's next to that
and I can click this drop down
to get a list of
different visualizers I can use.
So I'm going to use the JSON
visualizer because it's a JSON.
This time I get a lot
better of a formatted view.
So I can quickly view
this giant string and it's
proper format which is great.
Again, if you had a string
that's cater for HTML or XML,
then you can do that
as well or if you
have something that's catered for
something completely different,
you can also make
your own visualizers,
so that's pretty needed.
Also, if you just have
a giant paragraph of text
being stored in a variable,
you can just use the regular
text visualizer as well.
>> Cool.
>> So from there, now I
want to start looking
into some problems with
my application itself.
So I'm going to hit "Continue",
and so this is the general
application, and again,
I can go to
this rate books page where'll
randomly give me a list of
books that I can read to add
in my shelf or not read
and they won't be added.
So in my case, I just want to read
everything. So I'm going to add.
>> A hundred books.
>> Yeah, I'm going to
read all hundred of them.
>> How long will that take you?
>> It depends. Depends
on how big it is.
I have the goal every
year of reading 25 books.
So I'm not quite at
the 100 a year things,
so let's go with four years for 100.
But I'm noticing that
of the 100 books that
are supposed to be added to
the shelf when I do that,
it looks like there's
only around half of them.
So if I go into Visual Studio,
I want to double-check that
out but also I should receive
a notification if I click on
the "Rate Books" page telling
that all the books are gone.
Instead, I get a lovely
exception error instead.
So let's try to solve this issue.
I'm going to navigate to my
AddAlltoShell() function,
and this is my function
that will take each book on
the "Rate Books" page and
move them into my shelf.
I'm thinking the problem lies
within this for loop here.
So I want to see
what's going on here.
When I first started coding,
I was really big on
print statements everywhere.
Yeah, I don't know how many people
in the audience out there
love print statements as much
as I did but they're great.
>> Well, I graduated to
writing things to a text file.
>> Yeah, that's great
too, accounts logging.
But I guess the problem with
that at least for me was that it
would be all over my code
even when it's not needed,
I forget to delete it when I'm done.
So I prefer to not
modify my code nowadays.
If you do like to log your
information to the output window,
an alternative you can
use is a trace-point
which is an offshoot of
a regular breakpoint.
That will allow me to
essentially perform
a print statement without having
to modify my code in the process.
I'm going to set a normal breakpoint
inside this for loop first
and then I can hover over
the breakpoint to get
little settings icon.
When I click on that
I'm going to select
"Actions" and here I'll get a prompt
telling me what I want to
log to the output window.
In this case, I want to see
how many indices this for loop
goes there before it stops because
I feel like it's
stopping prematurely.
So I'm going to do index:{i} and
return the value of variable i.
Hit "Enter" and I'm
going to leave "Continue
Execution" checked but
if you wanted your code
to stop when a trace-point
is about to be printed,
you can do that as well.
You get a diamond icon instead
of the circle as well.
I'm going to boot up
the program again.
>> It would come in handy if you
wanted to watch
the progress of something.
I was working on some code yesterday
that looks in GitHub repositories
and it loops through
a large number of them and some of
them there was an exception
and I just wanted to
know which ones through
the exception without
watching this program go,
that could take hours.
So I wrote it to a file
which worked but
it seems like this way
I could just write
that information out to
the console window and then
I don't have this printing,
the saving to a file in my code,
which I could
accidentally released to
production and then it will
blow up because someone
didn't have the directory that
this is writing to, right?
>> Right.
>> The big risks in
modifying the code to do
debugging is you leave
that stuff in there.
>> Yeah, because I am
pretty sure I've done
a demo in school at
one point where I left
some arbitrary console.log
something rather,
and I always write weird quotes
in it when I'm frustrated
and trying to debug.
So like I said, like a random
[inaudible] right in
the middle of the demo.
>> What idiot wrote this code,
how comes this doesn't work?
>> From here, I'm going to perform
that same "Add All Books" to
My Shelf option and this time,
I should see some print
statements to go with it.
So going back into VS, I can go to
the output window and scroll up a
little bit and here you'll notice
that there's a bunch of
related print statements going
back with the trace-point
that I created.
This is one way to check out
your trace-points but also
the problem with this is that
these can easily get buried
in the sea of stuff
in the output window.
So the other place where you
can check them out that I
like is in the
diagnostic tools window.
This is the window that
I have a bad habit of
closing usually when I'm
debugging but one of
the perks of keeping it
open is this because you
can filter out events that you see.
>> I have a bad habit of leaving it
open and watching the pretty picture.
>> Yes, that's true too.
I do love the CPU graphs.
>> Yeah, but then what
are you doing with that?
>> But it makes you
look official when
somebody's walking past you,
what is that person doing?
>> Although I did use it in
this application I was working on
to tell if there was a problem
because the exceptions,
and there's like 10 exceptions
that just happen,
but then when I noticed
that there were 20,000
exceptions or 50,000
or 150,000 exceptions,
that was my clue
because the way this code
works if it hits an exception,
it just sits in a loop because
it's assuming that it
just needs to keep
trying and when I got to 400,000
exceptions that was my clue that,
hold on a second.
>> Like well, okay, maybe
I should do something.
You can view your
trace-points here as well
which might make things
a little easier too.
So from there, I'm noticing
that my index value,
i, only goes up to 49 when
it should go up to 99.
At this point, I just want
to step through like that
last iteration of my for loop just
to see what's going on
with each piece of it.
I'm going to go back to
where I set this trace-point
and now the new problem
is I want to go through
this for loop but I don't
want to start from
the very beginning of it,
like from when i is equal to zero
because I'll be there for
days and chances are I'm
not going to pay attention
and I'm going to skip when
i equals 49 and then I
have to rinse and repeat.
So I can use a conditional breakpoint
instead which will allow me to
halt my code only under
a specific scenario that I give it.
So where I set the trace-point,
I'm going to go back to settings
and I'm going to uncheck
"Actions" because I'm done with
this tracepoint and
check "Conditions".
From there, I want my code to
halt when i is equal to 49,
hit "Enter" and closeout.
The conditional breakpoint
has been created based off of
this little plus icon
inside the standard icon.
I'm going to have to
restart it again.
>> Now, those conditional breakpoints
are things have been in there for
pretty much all or I don't even
remember when those were created.
>> Yeah, I have no idea. I feel like
I started hearing about Visual Studio
around 2013 or whichever one
was before 2015.
>> 2013.
>> Yeah, '13.
So anything past
that, I have no idea.
Cool. Again, we're performing
that "Add All Books"
to My Shelf action.
My code halts this
time and you'll notice
that the value of i is set
to 49 instead of zero.
So from there if I step
through this for loop,
I'm noticing that I used my
neutralBooks.Count here as my loop
condition and at the same time,
a book is being removed from
neutralBooks at the end
of each iteration,
which is causing the count to
decrease at the start
of each new iteration.
So think I found the problem here.
So I'm going to stop debugging
and we're going to comment
out this line and then just clear
all the books at
the very end of the function
instead and that should solve
the issue, get rid of that.
>> Now, is there a way,
okay, let's say you thought
that was the issue,
you could add neutralBooks.Count
to the watch window, right?
>> Right.
>> But, correct me if I'm
wrong, but it doesn't update in
real-time as the application
is running; is that true?
>> Oh, it does update in real-time.
If you add it to the watch window
and you're stepping
then if it changes,
it will let you know that it changed
because it usually highlights in red
in either the watch
or in local's window.
>> All right. Good.
>> Cool. From there,
adding all books.
It's time it looks like there's
a lot more books that have been
added and just to double-check,
it turns out yeah,
I've rated all the books
in the library already.
That was conditional breakpoints
and tracepoints,
two awesome alternatives to
regular breakpoints that you can use
in your everyday
debugging environment.
>> Cool. So I think what
we'll do is stop here
and call this part one
and then next week
we'll do part two and see
more debugging tricks.
People want to learn more about that,
you wrote a blog post on this, right?
>> I did.
>> People can check out at
aka.ms/DebuggerDisplay.
>> Yeah, it goes through a lot more
of the different scenarios that you
can use with it and you can go
check it out for more examples.
>> We will see you next time
on Visual Studio Toolbox.
[MUSIC]

No comments:

Post a Comment