比Stackwalk更快

时间:2010-10-02 12:42:17

标签: c++ windows callstack

有没有人知道更好/更快的方式获得调用堆栈而不是“StackWalk”? 我也认为对于有很多变量的方法,stackwalk也会变慢... (我想知道商业剖析师会做什么?) 我在Windows上使用C ++。 :) 谢谢:))

3 个答案:

答案 0 :(得分:2)

我使用Jochen Kalmbachs StackWalker

speedet it up这样:

  • 在默认目录和PDB服务器中查找PDB files时,大部分时间都会丢失。

  • 我只使用one PDB path并为我想要解析的图片实现了white list(无需我查找user32.pdb)

  • 有时候我不需要深入到底部,所以我定义了一个max deep

代码更改:

BOOL StackWalker::LoadModules()
{

    ...

    // comment this line out and replace to your pdb path
    // BOOL bRet = this->m_sw->Init(szSymPath);
    BOOL bRet = this->m_sw->Init(<my pdb path>);

    ...

}

BOOL StackWalker::ShowCallstack(int iMaxDeep /* new parameter */ ... )
{

    ... 

// define a maximal deep
// for (frameNum = 0; ; ++frameNum )
    for (frameNum = 0; frameNum < iMaxDeep; ++frameNum )
    {

        ... 

    }
}

答案 1 :(得分:1)

查看http://msdn.microsoft.com/en-us/library/bb204633%28VS.85%29.aspx - 这是“CaptureStackBackTrace”,虽然它被称为“RtlCaptureStackBackTrace”。

答案 2 :(得分:0)

我不知道它是否更快,并且它不会显示任何符号,我相信你可以做得更好,但这是我在一段时间内写的一些代码,当我需要这些信息时(仅适用于Windows):

struct CallStackItem
{
    void* pc;
    CallStackItem* next;

    CallStackItem()
    {
        pc = NULL;
        next = NULL;
    }
};

typedef void* CallStackHandle;

CallStackHandle CreateCurrentCallStack(int nLevels)
{
    void** ppCurrent = NULL;

    // Get the current saved stack pointer (saved by the compiler on the function prefix).
    __asm { mov ppCurrent, ebp };

    // Don't limit if nLevels is not positive
    if (nLevels <= 0)
        nLevels = 1000000;

    // ebp points to the old call stack, where the first two items look like this:
    // ebp -> [0] Previous ebp
    //        [1] previous program counter
    CallStackItem* pResult = new CallStackItem;
    CallStackItem* pCurItem = pResult;
    int nCurLevel = 0;

    // We need to read two pointers from the stack
    int nRequiredMemorySize = sizeof(void*) * 2;
    while (nCurLevel < nLevels && ppCurrent && !IsBadReadPtr(ppCurrent, nRequiredMemorySize))
    {
        // Keep the previous program counter (where the function will return to)
        pCurItem->pc = ppCurrent[1];
        pCurItem->next = new CallStackItem;

        // Go the the previously kept ebp
        ppCurrent = (void**)*ppCurrent;
        pCurItem = pCurItem->next;
        ++nCurLevel;
    }

    return pResult;
}

void PrintCallStack(CallStackHandle hCallStack)
{
    CallStackItem* pCurItem = (CallStackItem*)hCallStack;
    printf("----- Call stack start -----\n");
    while (pCurItem)
    {
        printf("0x%08x\n", pCurItem->pc);
        pCurItem = pCurItem->next;
    }
    printf("-----  Call stack end  -----\n");
}

void ReleaseCallStack(CallStackHandle hCallStack)
{
    CallStackItem* pCurItem = (CallStackItem*)hCallStack;
    CallStackItem* pPrevItem;
    while (pCurItem)
    {
        pPrevItem = pCurItem;
        pCurItem = pCurItem->next;
        delete pPrevItem;
    }
}