使用FramesToSkip的CaptureStackBackTrace不一致

时间:2019-04-25 13:36:50

标签: c winapi stack-trace

在Windows上,您可以使用CaptureStackBackTrace作为

来捕获堆栈跟踪
void* frames[USHRT_MAX];
USHORT framesCount = CaptureStackBackTrace(0, USHRT_MAX, frames, NULL);

但是,在循环中用较小的块捕获它以避免避免分配USHRT_MAX缓冲区不会提供相同的结果。

此代码

#include <Windows.h>
#include <assert.h>
#include <stdio.h>

__declspec(noinline) void CheckStack(void)
{
    printf("Checking stack...\n");

    void* entireStack[USHRT_MAX];
    USHORT frameCount = CaptureStackBackTrace(0, USHRT_MAX, entireStack, NULL);

    printf("Stack size is: %u\n", frameCount);

    ULONG frameOffset = 1;

    for (;;)
    {
        void* chunk[64];
        USHORT framesFound = CaptureStackBackTrace(frameOffset, 64, chunk, NULL);
        if (framesFound)
        {
            if (memcmp(entireStack + frameOffset, chunk, sizeof(chunk)) != 0)
            {
                printf("Incorrect content\n");
            }

            frameOffset += (ULONG)framesFound; 
        }
        else
        {
            break;
        }
    }

    if (frameCount != frameOffset)
    {
        printf("Incorrect count (%u != %u)\n", frameCount, frameOffset);
    }

    printf("Done\n");
}

__declspec(noinline) void Test(int i)
{
    if (i != 500)
        Test(++i);
    else
        CheckStack();
}

int main()
{
    Test(0);
}

产生以下输出

Checking stack...
Stack size is: 507
Incorrect count (507 != 257)
Done

cl /Od main.c /link /OUT:main.exe进行构建时。

我是否错误地使用了FramesToSkip参数?为什么计数不相等?

1 个答案:

答案 0 :(得分:0)

如果您使用的是Windows Server 2003和Windows XP,则

  

FramesToSkip和FramesToCapture参数的总和必须为   小于63。

在文档中。

否则,正如@RbMm所说,在API源代码中,有以下逻辑:

if(FramesToSkip>0xfe)
{
    return 0;  //There are too many stack structures skipped, returning directly to 0.
}

但是,在CaptureStackBackTraceRtlCaptureStackBackTrace中的msdn上均未提及此内容。 我不会在这里发布源代码,而是在调试中证明它:

1。创建一个示例:

#include <Windows.h>
#include <assert.h>
#include <stdio.h>

__declspec(noinline) void CheckStack(void)
{
    void* entireStack[USHRT_MAX];
    USHORT frameCount = CaptureStackBackTrace(255, USHRT_MAX, entireStack, NULL);
}

__declspec(noinline) void Test(int i)
{
    if (i != 500)
        Test(++i);
    else
        CheckStack();
}

int main()
{
    Test(0);
}

2。进入反汇编中的CaptureStackBackTraceenter image description here 您会看到dword ptr[ebp+8](堆栈中推入的CaptureStackBackTrace的第一个参数)将与0feh(254)进行比较。如果为true,则返回0。