- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在下面的代码中,函数foo
递归调用了一次。内部调用导致引发访问冲突。外部调用捕获异常。
#include <windows.h>
#include <stdio.h>
void foo(int cont)
{
__try
{
__try
{
__try
{
if (!cont)
*(int *)0 = 0;
foo(cont - 1);
}
__finally
{
printf("inner finally %d\n", cont);
}
}
__except (!cont? EXCEPTION_CONTINUE_SEARCH: EXCEPTION_EXECUTE_HANDLER)
{
printf("except %d\n", cont);
}
}
__finally
{
printf("outer finally %d\n", cont);
}
}
int main()
{
__try
{
foo(1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
printf("main\n");
}
return 0;
}
这里的预期输出应该是
inner finally 0
outer finally 0
inner finally 1
except 1
outer finally 1
但是,outer finally 0
在实际输出中明显缺失。这是错误还是我忽略了一些细节?
为了完整起见,发生在 VS2015 上,针对 x64 进行编译。令人惊讶的是,它并没有发生在 x86 上,这让我相信这确实是一个错误。
最佳答案
存在且更简单的示例(我们可以删除内部 try/finally
block :
void foo(int cont)
{
__try
{
__try
{
if (!cont) *(int *)0 = 0;
foo(cont - 1);
}
__except (cont? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
printf("except %d\n", cont);
}
}
__finally
{
printf("finally %d\n", cont);
}
}
有输出
except 1
finally 1
所以 finally 0
block 没有执行。但在非递归情况下 - 没有错误:
__try
{
foo(0);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
printf("except\n");
}
输出:
finally 0
except
这是下一个函数的错误
EXCEPTION_DISPOSITION
__C_specific_handler (
_In_ PEXCEPTION_RECORD ExceptionRecord,
_In_ PVOID EstablisherFrame,
_Inout_ PCONTEXT ContextRecord,
_Inout_ PDISPATCHER_CONTEXT DispatcherContext
);
此函数的旧实现有错误 here :
//
// try/except - exception filter (JumpTarget != 0).
// After the exception filter is called, the exception
// handler clause is executed by the call to unwind
// above. Having reached this point in the scan of the
// scope tables, any other termination handlers will
// be outside the scope of the try/except.
//
if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget) { // bug
break;
}
如果我们安装了最新的 VC 编译器/库,请搜索 chandler.c
(在我的安装中位于 \VC\crt\src\amd64\chandler.c
)
现在可以在文件中查看下一个代码:
if (TargetPc == ScopeTable->ScopeRecord[Index].JumpTarget
// Terminate only when we are at the Target frame;
// otherwise, continue search for outer finally:
&& IS_TARGET_UNWIND(ExceptionRecord->ExceptionFlags)
) {
break;
}
因此添加了附加条件 IS_TARGET_UNWIND(ExceptionRecord->ExceptionFlags)
以修复此错误
__C_specific_handler
在不同的 crt 库中实现(在某些情况下使用静态链接,在某些情况下将从 vcruntime*.dll
或 msvcrt.dll< 导入
(转发到 ntdll.dll
)。还 ntdll.dll
导出此函数 - 但是在最新的 win10 builds(14393) 中它仍然没有修复
关于c++ - __finally 应该在 EXCEPTION_CONTINUE_SEARCH 之后运行吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32805892/
我在我正在处理的新模块中遇到堆栈损坏问题,该模块是大型遗留项目的一部分。我的代码是使用 Borland C++Builder 5.0 用 C++ 编写的。 我已将问题跟踪到以下函数: // Note:
在下面的代码中,函数foo 递归调用了一次。内部调用导致引发访问冲突。外部调用捕获异常。 #include #include void foo(int cont) { __try
我有一个主要用 C 编写的库,它的某些部分应该是线程安全的,并且我使用全局自旋锁来保护代码的关键部分。 现在我的问题是: 我应该从受自旋锁保护的关键部分内部调用用户的一些回调,以防这些回调生成异常,在
我认为这段代码是否正确: try { Screen->Cursor = crHourGlass; try { throw Exception("
我是一名优秀的程序员,十分优秀!