2013-03-22 216 views
1

我有用C++/CX编写的Windows应用商店应用(用于Windows 8),并且我在try/catch块中包装了一段代码。C++/CX发现异常 - 如何打印整个堆栈?

catch块工作和捕捉到一个例外,但到目前为止,我只似乎能够打印出异常的“消息”的一部分,而不是完整的异常堆栈:

try 
{ 
... 
} 
catch(Exception^ e) 
{ 
    LogMessage("Exception caught: " + e->ToString()); 
} 

当异常被捕获时,输出的LogMessage只有以下文字:

"Exception caught: The object already exists" 

我已经试过E-> toString()和E->消息,但都产生相同的输出,并且不包括完整的例外叠加。

在C#中,似乎很容易输出完整的异常堆栈,所以我不确定为什么在C++/CX中看起来很困难?

+0

更新了标签,你所要求的标签超出了C++标准,并且只是一个C++/CR问题 – 2013-03-22 03:20:12

回答

2

这在C++/CX中很困难,因为确定堆栈中的函数需要解析调试符号的代码。在C#中,CLR在运行时确实可以记住堆栈中的哪些方法,但在C++/CX中,函数的名称不会记录在生成的二进制文件中。换句话说,你在C#中获得的堆栈跟踪取决于C#特性:反射。

此外,调用一个普通的COM API而不是C++/CX API的代码可能会导致异常。在这种情况下,异常是从错误HRESULT下面的返回代码生成的,而不是在引发异常时。 (事实上​​,每当跨越组件边界时都会发生这种情况;即使操作的两边都是C++/CX,也会用纯COM处理)。因此,跟踪所需的堆栈不再可用。

C++异常不会记录堆栈跟踪。另一方面,从本地程序中,您可以在发生未处理的异常时收集小型转储,这样您可以在需要时使用调试器查看堆栈。

+0

感谢您的好解释 – DaveUK 2013-03-22 03:13:27

1

请记住,C++/CX程序是纯粹的非托管C++代码。 CX语言扩展只能让您在C++代码中轻松使用WinRT类型,它隐藏了COM实现细节。所以它得到了代码优化器的完整处理。 不是试图确保堆栈走可以安全地执行。特别是在不会抛出异常的叶函数中。它很容易省略设置EBP寄存器,这是指示堆栈激活帧的基础的重要指标。

托管代码中不是这种情况,例如C#。在垃圾收集运行时环境中,堆栈走是非常重要的。垃圾收集器必须执行它们才能在收集垃圾时查找对象引用。代码访问安全性还取决于栈走。一个令人愉快的副作用是现在对于异常生成堆栈跟踪也变得非常容易。它甚至暴露在框架api中,StackTrace类允许您在自己的代码中使用堆栈。

没有简单的解决方法,你需要调试符号来拍摄它。和DbgHelp api中的StackWalk64。由于程序崩溃在某个Windows函数的某处,因此您仍然无法获取任何信息。速度在C++中胜过了方便。

+0

感谢您的好解释 – DaveUK 2013-03-22 03:13:53