问题标签 [structured-exception]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 混合 C++ 异常处理和 SEH (windows)
我有一个函数,我调用它getaddrinfo()
来获取sockaddr*
系统分配的目标内存。许多人可能知道,您需要调用freeaddrinfo()
以释放由 getaddrinfo() 分配的内存。
现在,在我的函数中,有几个地方我可能会抛出异常,因为某些函数失败了。我的第一个解决方案是将其合并freeaddrinfo()
到每个 if 块中。但这对我来说确实很难看,因为无论如何我都必须在函数返回之前调用它,所以我想出了 SEH 的 try-finally ......
但是我遇到的问题是,不允许将 throw-statements 编码到 __try-block
然后,我在 msdn 上阅读并尝试将 throw 语句交换到从 __try-block 中调用的辅助函数中......瞧,编译器不再抱怨它了......
这是为什么?这安全吗?这对我来说没有意义:/
代码:
编辑:
尝试了以下方法,它适用于抛出一个整数,但当我使用一个类作为异常时不起作用:
为什么?:/
c++ - 结构化异常处理程序 (SEH) 不会捕获堆损坏
我正在编写使用 3rd 方库执行一项简单任务(光栅化)的小型实用程序(VC 2010,无 clr)。以后的实用程序将被更大的应用程序使用。有时,由于 3rd 方库中的一些堆损坏,实用程序会崩溃。没关系,但 Windows (Vista/2008) 显示众所周知的对话框“程序已停止工作......关闭/调试程序”。这在我的情况下不合适(服务器端)。实用程序应在没有任何可见效果的情况下静默崩溃/终止。
为此,我为未处理的异常 (SetUnhandledExceptionFilter) 安装了 SEH。对于像 AV ( *(PDWORD)0 = 0 ) 这样的异常,处理程序被完美地调用,但由于某种原因,它不会在堆损坏的情况下被调用。在卸载第 3 方库 dll 之一的 dllmain 时发生损坏。
几个问题。谁能解释为什么不调用处理程序?还有其他方法可以防止该对话吗?
windows - 为什么 64 位 Windows 不能解除用户-内核-用户异常?
如果堆栈跨越内核边界,为什么 64 位 Windows 不能在异常期间展开堆栈 - 而 32 位 Windows 可以?
整个问题的背景来自:
背景
在 32 位 Windows 中,如果我在我的用户模式代码中抛出异常,该异常是从内核模式代码回调的,它是从我的用户模式代码调用的,例如:
Windows 中的结构化异常处理 (SEH) 可以展开堆栈,通过内核模式展开,回到我的用户代码,在那里我可以处理异常并且我看到有效的堆栈跟踪。
但不是在 64 位 Windows 中
64 位版本的 Windows 不能这样做:
由于复杂的原因,我们无法将异常传播回 64 位操作系统(amd64 和 IA64)。自从 Server 2003 的第一个 64 位版本以来,情况就一直如此。在 x86 上,情况并非如此——异常通过内核边界传播,最终将帧返回
而且由于在这种情况下无法返回可靠的堆栈跟踪,因此必须做出决定:让您看到无意义的异常,或者完全隐藏它:
当时的内核架构师决定采取保守的 AppCompat-friendly 方法——隐藏异常,并寄希望于最好的结果。
本文继续讨论所有 64 位 Windows 操作系统的行为方式:
- Windows XP 64 位
- Windows Server 2003 64 位
- Windows Vista 64 位
- Windows Server 2008 64 位
但从 Windows 7(和 Windows Server 2008)开始,架构师改变了他们的想法——在某种程度上。仅对于64 位应用程序(不是 32 位应用程序),它们将(默认情况下)停止抑制这些用户-内核-用户异常。因此,默认情况下,打开:
- Windows 7 64 位
- 视窗服务器 2008
所有 64 位应用程序都会看到这些异常,它们以前从未见过它们。
在 Windows 7 中,当原生 x64应用程序以这种方式崩溃时,程序兼容性助手会收到通知。如果应用程序没有Windows 7 清单,我们会显示一个对话框,告诉您 PCA 已应用应用程序兼容性 shim。这是什么意思?这意味着,下次您运行应用程序时,Windows 将模拟 Server 2003 的行为并使异常消失。请记住,Server 2008 R2 上不存在 PCA,因此此建议不适用。
所以这个问题
问题是为什么64 位 Windows 无法通过内核转换来展开堆栈,而 32 位版本的 Windows 可以?
唯一的提示是:
由于复杂的原因,我们无法将异常传播回 64 位操作系统(amd64 和 IA64)。
提示是复杂的。
我可能不明白这个解释,因为我不是操作系统开发人员 - 但我想知道为什么。
更新:停止抑制 32 位应用程序的修补程序
Microsoft 发布了一个修补程序,使 32 位应用程序也不再抑制异常:
KB976038:在 64 位版本的 Windows 中运行的应用程序引发的异常被忽略
- 在回调例程中引发的异常在用户模式下运行。
在这种情况下,此异常不会导致应用程序崩溃。相反,应用程序进入不一致的状态。然后,应用程序抛出一个不同的异常并崩溃。
用户模式回调函数通常是由内核模式组件调用的应用程序定义的函数。用户模式回调函数的示例是 Windows 过程和挂钩过程。Windows 调用这些函数来处理 Windows 消息或处理 Windows 挂钩事件。
然后,此修补程序可让您阻止 Windows 全局吃掉异常:
或每个应用程序:
该行为也记录在 XP 和 Server 2003 的 KB973460 中:
一个提示
在研究使用 xperf 在 64 位 Windows 上捕获堆栈跟踪时,我发现了另一个提示:
Xperf 中的堆栈行走
禁用寻呼执行器
为了在 64 位 Windows 上进行跟踪,您需要设置DisablePagingExecutive注册表项。这告诉操作系统不要将内核模式驱动程序和系统代码分页到磁盘,这是使用 xperf 获取 64 位调用堆栈的先决条件,因为 64 位堆栈遍历依赖于可执行映像中的元数据,并且在某些情况下xperf堆栈遍历代码不允许触摸分页页面。从提升的命令提示符运行以下命令将为您设置此注册表项。
设置此注册表项后,您需要重新启动系统才能记录调用堆栈。设置此标志意味着 Windows 内核将更多页面锁定到 RAM 中,因此这可能会消耗大约 10 MB 的额外物理内存。
这给人的印象是,在 64 位 Windows 中(并且仅在 64 位 Windows 中),您不允许遍历内核堆栈,因为磁盘上可能有页面输出。
winapi - 如何在特定功能上通过 /EHsc 获得 /EHa 的好处?
如果我知道extern "C"
我的程序中的特定函数(例如,RaiseException
)是引发 SEH 异常的唯一函数,并且我希望它们转换为 C++ 异常,那么我有什么方法可以“选择性地启用”/EHa
该函数,以便异常被转换为CStructured_Exception
没有膨胀或减慢程序的其余部分,通常是由/EHa
?
c++ - _set_se_translator 的“get”等价物?
我需要使用当前的翻译器手动翻译结构化异常。
我如何“获得”某人设定的价值_set_se_translator
?
c++ - 将外部错误代码映射到 std::error_condition
我正在考虑修改我们必须使用新的 C++11 error_code/error_condition/exception mechanisim的 MS 结构化异常到异常映射代码。
我的理解是,一般理念是您应该首先尝试将错误代码映射到 std::error_condition 代码,否则,请制作自己的自定义 error_condition 代码。
我看到的问题是std::errc非常适合处理 POSIX 错误。如果我从具有与典型操作系统调用完全不同的错误范围的源获取代码,则它的映射不正确。
例如,让我们以Microsoft 的 SEH 代码为例。这些来自操作系统,因此理论上它应该映射以及 POSIX 之外的任何内容。但它肯定似乎根本无法很好地映射:
那么攻击这个的最好方法是什么?
visual-c++ - 如何处理 Visual Studio C++ 中的访问冲突?
通常访问冲突会终止程序,我无法使用try
and捕获 Win32 异常catch
。有没有办法让我的程序运行,即使在访问冲突的情况下?最好我想处理异常并向用户显示发生了访问冲突。
编辑:我希望我的程序非常健壮,即使是针对编程错误。我真正想避免的事情是程序终止,即使以某些损坏状态为代价。
c++ - Best place to call MiniDumpWriteDump() to catch a crash
I have a large-ish Win32 program that I'm maintaining, and I'd like to instrument it to automatically and unconditionally generate a minidump file whenever something bad happens. I can't ask customers to install userdump.exe, and I can't ask them to install visual studio.
Is there a good way of doing this? I'd like to be able to generate a minidump whether abort() is called from our assert handler (which is complicated), whether someone touches bad memory, or anything else really bad happens.
On Posix, I'd install a signal handler and be done with this. My understanding is that the equivalent approach on Windows is SEH, but our program starts up a lot of threads in a lot of different places so it would be very painful to wrap every thread entry point with a __try/__catch.
Ideas?
c++ - 如何通过 COM 公开通过结构化异常处理捕获的异常?
我用 Visual C++ 实现的 COM 服务器使用了大量其他 C++ 代码。其他 C++ 代码有时会将代码包装在__try
-__except
并将结构化异常转换为自定义 C++ 异常。这部分我无法改变。
我的 COM 服务器的任何方法都不应该让这些异常通过 COM 边界传播,因此它必须捕获并将它们转换为HRESULT
s。那些自定义 C++ 异常包含在翻译过程中获得的原始错误代码 - 它类似于EXCEPTION_ACCESS_VIOLATION
. 问题是我如何制作一个适当的HRESULT
值,以便客户端尽可能多地了解发生的事情(并且可能在看到访问冲突后决定重新启动服务器(以及在 inproc 的情况下重新启动服务器))。
假设它是EXCEPTION_ACCESS_VIOLATION
在WinBase.h
后者定义在WinNT.h
我可以使用HRESULT_FROM_WIN32()
将该代码转换为首先HRESULT
假设它是Win32 错误。
我HRESULT_FROM_WIN32()
在这里使用还是使用任何其他方式进行翻译?
c++ - __finally 应该在 EXCEPTION_CONTINUE_SEARCH 之后运行吗?
在下面的代码中,函数foo
递归调用自身一次。内部调用会引发访问冲突。外部调用捕获异常。
这里的预期输出应该是
但是,outer finally 0
实际输出中明显缺失。这是一个错误还是我忽略了一些细节?
为了完整起见,VS2015 发生,为 x64 编译。令人惊讶的是它不会发生在 x86 上,这让我相信它确实是一个错误。