示例#1
0
    internal static CallstackFunction[] GetObjects(List <string> frameNames)
    {
        int frameCount = frameNames.Count;

        // Stop the stack if we reach the max callstack depth
        if (frameCount > TracepointAnalysis.MaxCallstackDepth)
        {
            frameCount = TracepointAnalysis.MaxCallstackDepth;
        }

        //// Sometimes helpful: Stop the stack if we hit rpcrt4.dll since this marks a COM transition
        //for (int c = 0; c < frameCount; c++)
        //{
        //    if (frameNames[c].Contains("rpcrt4.dll"))
        //    {
        //        frameCount = c;
        //        break;
        //    }
        //}

        CallstackFunction[] result = new CallstackFunction[frameCount];
        for (int c = 0; c < frameCount; c++)
        {
            result[c] = GetObject(frameNames[c]);
        }

        return(result);
    }
示例#2
0
 private static bool IsFunctionInList(CallstackFunction function, List <CallTreeNode> callTreeRoots)
 {
     foreach (CallTreeNode node in callTreeRoots)
     {
         if (node.Function == function)
         {
             return(true);
         }
     }
     return(false);
 }
示例#3
0
    private static CallstackFunction GetObject(string frameName)
    {
        if (s_dict == null)
        {
            s_dict = new Dictionary <string, CallstackFunction>();
        }

        CallstackFunction @this;

        if (!s_dict.TryGetValue(frameName, out @this))
        {
            @this = new CallstackFunction(frameName);
            s_dict.Add(frameName, @this);
        }

        return(@this);
    }
    static void Main(string[] args)
    {
        List <Callstack>    stacks;
        List <CallTreeNode> callTreeRoots;

        CallstackFilter filter = delegate(CallstackKey key)
        {
            // This function can be used to remove functions that you think are unrelated to the leak.
            // Example:
            //  if (key.Contains("FunctionWithBalancedAddRefsAndReleases"))
            //      return false;

            return(true);
        };

        TracepointAnalysis.MaxCallstackDepth = 50;

        TracepointAnalysis.ReadFile(@"C:\Users\greggm\Desktop\leakdiag.txt", filter, out stacks, out callTreeRoots);

        TracepointAnalysis.ComputeAddRefReleaseDeltas(callTreeRoots);

        int       totalDelta    = callTreeRoots[0].Function.DeltaValue + callTreeRoots[1].Function.DeltaValue;
        const int expectedDelta = 2;

        if (totalDelta != expectedDelta)
        {
            if (totalDelta <= 0)
            {
                Console.WriteLine("AddRef/Release problem went away");
            }
            else
            {
                Console.WriteLine("AddRef/Release problem is bigger than expected");
            }

            return;
        }

        CallstackFunction.DumpFunctionsWithDelta(2);
        DumpStacks(stacks);
        //DumpCallTree(callTreeRoots);
    }
示例#5
0
    static private CallTreeNode AddNode(Dictionary <CallstackFunction, CallTreeNode> dict, CallstackFunction frame)
    {
        CallTreeNode node;

        if (dict.TryGetValue(frame, out node))
        {
            node.m_hitCount++;
            return(node);
        }
        else
        {
            node = new CallTreeNode(frame);
            dict.Add(frame, node);

            return(node);
        }
    }
示例#6
0
 private CallTreeNode(CallstackFunction frame)
 {
     this.Function   = frame;
     this.Children   = new Dictionary <CallstackFunction, CallTreeNode>();
     this.m_hitCount = 1;
 }
示例#7
0
    /// <summary>
    /// Reads in a file that contains the text from the debugger's output window and analyises the tracepoint callstacks
    /// </summary>
    /// <param name="path">Path to a file containing the saved output window text</param>
    /// <param name="filter">Optional delegate to filter out callstacks that are uninteresting</param>
    /// <param name="stacks">Returns a list of all the callstacks in the output with their hit count</param>
    /// <param name="callTreeRoots">Returns the roots of the tracepoint call trees</param>
    static public void ReadFile(string path, CallstackFilter filter, out List <Callstack> stacks, out List <CallTreeNode> callTreeRoots)
    {
        int currentLine     = 0;
        int currentRefCount = 0;

        Dictionary <CallstackFunction, CallTreeNode> callTreeRootMap = new Dictionary <CallstackFunction, CallTreeNode>();
        Dictionary <CallstackKey, Callstack>         callstackMap    = new Dictionary <CallstackKey, Callstack>();

        stacks = new List <Callstack>();

        StreamReader inputFile = File.OpenText(path);

        List <string> currentCallstack         = null;
        Regex         callstackStartLineFormat = new Regex(@"[0-9]+\:\ ?\t.+(\.dll|\.exe)\!.+");

        while (!inputFile.EndOfStream)
        {
            currentLine++;
            string line = inputFile.ReadLine();

            if (currentCallstack == null)
            {
                Match match = callstackStartLineFormat.Match(line);

                if (match.Success && match.Index == 0)
                {
                    string s = line.Substring(line.IndexOf('\t') + 1).Trim();

                    //Additional code to validate the debug output. Useful when figuring out why a
                    //call stack may have gotten dropped.
                    string refcountStr = line.Substring(0, line.IndexOf(':'));
                    int    newRefCount = int.Parse(refcountStr);

                    // mscordbi - ignore the 'InterlockedCompareExchange frame'
                    if (inputFile.EndOfStream)
                    {
                        Debugger.Break();
                    }
                    currentLine++;
                    line = inputFile.ReadLine();
                    s    = line.Substring(line.IndexOf('\t') + 1).Trim();

                    // Is an AddRef frame?
                    if (s.EndsWith("::AddRef") || s.Contains("InterlockedIncrement"))
                    {
                        if (newRefCount != currentRefCount + 1)
                        {
                            //Debugger.Break();
                        }
                        currentRefCount++;
                    }
                    // Is a release frame?
                    else if (s.EndsWith("::Release") || s.Contains("InterlockedDecrement"))
                    {
                        if (newRefCount != currentRefCount - 1)
                        {
                            //Debugger.Break();
                        }
                        currentRefCount--;
                    }
                    else
                    {
                        Debugger.Break();
                    }

                    // Create a new call stack
                    currentCallstack = new List <string>();
                    currentCallstack.Add(s);
                    currentRefCount = newRefCount;
                }
            }
            else
            {
                if (IsOnlyWhiteSpace(line))
                {
                    CallstackFunction[] frames = CallstackFunction.GetObjects(currentCallstack);
                    CallstackKey        key    = new CallstackKey(frames);

                    if (filter == null || filter(key))
                    {
                        Callstack.AddCallstack(stacks, callstackMap, key);
                        CallTreeNode.AddCallstack(callTreeRootMap, key);
                    }

                    currentCallstack = null;
                }
                else if (line.Length > 1 && line[0] == '\t')
                {
                    string s = line.Substring(1);

                    currentCallstack.Add(s);
                }
            }
        }

        callTreeRoots = new List <CallTreeNode>(callTreeRootMap.Values);
    }