diagnostics
diagnostics copied to clipboard
Pinpointing a static gcroot with sos
How can I determine which static field of which class is responsible for the static reference when using gcroot command. The result of gcroot only shows the types.
@mikem8361
I'm not sure is gcroot
can tell you the name of the static roots. @Maoni0, @cshung, @dotnet/dotnet-diag any ideas?
I can't think of anything short of adding a full pass of symbol support on SOS.
if I see this pattern - pinned handle -> object[] -> object
I will just assume that those are very likely static objects because static objects are always in an object[] pointed to by a pinned handle :smile:
With SOS today I am not aware of any option better than educated guessing/detective work. What @Maoni0 wrote is a very good heuristic for "Is this a static field reference?" If you further want to know what type and field the reference is through you can often get good clues by examining the type or examining the content of the object and then correlating what you see back to the source code.
With more development work on SOS this story could be improved. SOS could enumerate every loaded type, then enumerate every static field to determine which, if any, matched a given object of interest. I don't recall offhand but it is possible that Visual Studio's memory snapshot analysis already does that. If no tool has the feature right now you could probably write a write a tiny console app using CLRMD to automate that search for you.
Thanks, Visual Studio can show the path.
@noahfalk
@EventHorizon1024 don't use concurrent bag, it's a trap 😄
- https://github.com/dotnet/runtime/issues/23103
- https://github.com/dotnet/runtime/issues/2382
I ran into this today. It would have been really nice to have had this feature in SOS for something I'm investigating in AzureWatson. (Yep, it was ConcurrencyBag.)
I'm assigning this to myself, it should be fixable, but we'll probably have to put it behind a flag like -resolveStatics
since this will be very slow in large dump files. We have to enumerate every static/threadstatic field (the APIs don't support lookup by address) and that takes a ton of time in processes with a lot of types and modules.