2010-10-02 21 views
4

Quelqu'un sait-il d'un meilleur/plus rapide pour obtenir la pile d'appels que « StackWalk »? Je pense aussi que stackwalk peut aussi être plus lent sur les méthodes avec beaucoup de variables ... (je me demande ce que profileurs commerciales font?) J'utilise C++ sur Windows. :) merci :)plus vite que Stackwalk

+1

Valgrind? http://stackoverflow.com/questions/413477/is-there-a-good-valgrind-substitute-for-windows – t0mm13b

+0

hmmm ... n'est pas valgrind seulement pour unix? – Idov

+0

et valgrind instrumentation, je cherche un meilleur moyen d'échantillonner la pile ... – Idov

Répondre

0

Je ne sais pas si c'est plus rapide, et il ne vous montrera aucun symbole, et je suis sûr que vous pouvez faire mieux que cela, mais c'est un code que j'ai écrit un certain temps quand je avais besoin de cette information (fonctionne uniquement pour 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; 
    } 
} 
1

J'utilise Jochen Kalmbachs StackWalker (http://stackwalker.codeplex.com/).

Je speedet it up ainsi:

  • La plupart du temps est perdu dans la recherche de la PDB files dans les répertoires par défaut et les serveurs PDB.

  • Je n'utilise que one PDB path et mis en œuvre un white list pour les images que je veux se résoudre (pas besoin pour moi de chercher des user32.pdb)

  • Parfois, j'ai besoin de plonger au fond, donc je a défini un max deep

changements de code:

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) 
    { 

     ... 

    } 
} 

La nouvelle version (supporti g VS2010) de StackWalker est au Codeplex. La documentation est toujours au CodeProject.