我的问题是,什么可能导致调用RcConsolidateFrames?这会混淆调用堆栈吗?
我正在努力获得用于在C ++中进行调试的良好调用堆栈(我可以在那里进行更多细节,但希望将其专注于一个可回答的问题)。我们正在使用带有/ EHa的Visual Studio 2013(v120)编译器(异步 - 基本上也获得SEH)异常处理。由于使用/ EHa,在try-catch(...)块中,我们将所有异常视为致命异常,并且在catch(...)块的末尾,我们使用throw;
重新抛出异常
我一直在尝试在C ++的异常处理工具箱(UnhandledExceptionFilter,Try-Catch,Abort Handlers等)中找到各种工具的正确组合,以便在尽可能多的情况下让我们获得可靠的调用堆栈。现在,我可以获得一个很好的调用堆栈(通过'好'我的意思是它指向抛出异常的行),生产代码中只有一个UnhandledExceptionFilter。当我开始添加任何try-catch行为时,它开始变得混乱。
长话短说,我可以在测试程序中添加一些try-catch块,这些块的行为与我期望的一样。在我们的生产代码中,它的行为有所不同,我不知道为什么。我一直在寻找线索,我发现的一条线索是调用堆栈中的这一行:ntdll.dll!RcConsolidateFrames() Unknown
。在我们其中一个类的ctor周围添加try-catch块后,我看到了这一行。此时,调用堆栈接近(ish)但不包括throw。以下是生产代码中的示例调用堆栈,其中一些名称已更改:
> KernelBase.dll!RaiseException() Unknown
msvcr120d.dll!__RethrowException(EHExceptionRecord * pThisException) Line 1234 C++
msvcr120d.dll!__CxxCallCatchBlock(_EXCEPTION_RECORD * pExcept) Line 1296 C++
ntdll.dll!RcConsolidateFrames() Unknown
OneOfOurDlls.dll!OurNamespace::someFunction() Line 72 C++
OurMainProgram.exe!wmain(int argc, wchar_t * * argv) Line 39 C++
[External Code]
这是一个简单的示例程序,我可以在我的桌面上运行,它为我提供了我期望的行为,并且在生产中没有看到类似的情况(没有RcConsolidateFrames)。
Main.cpp
#include "A.h"
#include <Windows.h>
#include <iostream>
#include <memory>
LONG WINAPI UnhandledExceptionFilter(_In_ struct _EXCEPTION_POINTERS *ExceptionInfo)
{
std::cout << "!!!*** UnhandledExceptionFilter ***!!!" << std::endl;
return EXCEPTION_CONTINUE_SEARCH;
}
void main()
{
std::cout << "main()" << std::endl;
SetUnhandledExceptionFilter(UnhandledExceptionFilter);
try
{
auto a = std::make_unique<A>();
a->createB(true);
}
catch (...)
{
std::cout << "main() -- catch(...)" << std::endl;
throw;
}
}
A.h A.cpp
#pragma once
class A
{
public:
A();
~A();
void createB(bool bThrowsInCtor);
};
#include "A.h"
#include "B.h"
#include <iostream>
#include <memory>
A::A()
{
std::cout << " A::A()" << std::endl;
}
A::~A()
{
std::cout << " A::~A()" << std::endl;
}
void A::createB(bool bThrowsInCtor)
{
try
{
std::cout << " A::createB -- throws = " << bThrowsInCtor << std::endl;
auto b = std::make_unique<B>(bThrowsInCtor);
}
catch (...)
{
std::cout << " A::createB -- catch(...)" << std::endl;
throw;
}
}
B.h B.cpp
#pragma once
class B
{
public:
B(bool throws);
~B();
};
#include "B.h"
#include <iostream>
B::B(bool throws)
{
std::cout << " B::B()" << std::endl;
if (throws)
{
std::cout << " throwing std::runtime_error" << std::endl;
throw std::runtime_error("B::B()");
}
}
B::~B()
{
std::cout << " B::~B()" << std::endl;
}
输出
main()
A::A()
A::createB -- throws = 1
B::B()
throwing std::runtime_error
A::createB -- catch(...)
A::~A()
main() -- catch(...)
!!!*** UnhandledExceptionFilter ***!!!
Good Call Stack
KernelBase.dll!_RaiseException@16() Unknown
[External Code]
> BlankVS2013Project.exe!B::B(bool throws) Line 12 C++
[External Code]
BlankVS2013Project.exe!A::createB(bool bThrowsInCtor) Line 21 C++
BlankVS2013Project.exe!main() Line 23 C++
[External Code]