Ali*_*Ali 5 c c++ winapi mingw exception
我正在使用mingw g ++ 4.6.1和-O0,WinXP SP2.
g ++配置了--disable-sjlj-exceptions --with-dwarf2.
GetLastError() 返回0或2,取决于抛出异常的方式:
throw runtime_error(error_message());
Run Code Online (Sandbox Code Playgroud)
伪造"错误代码:0"打印,并且
const string msg = error_message();
throw runtime_error(msg);
Run Code Online (Sandbox Code Playgroud)
按预期打印"错误代码:2".
首先,我认为GetLastError()调用了两次,但调试显示它正如预期的那样被调用一次.
到底是怎么回事?
Gre*_*ill 10
有可能throw在某个地方设置调用Win32 API函数的代码将Last-Error值重置为0.这可能在您调用之前发生error_message().
呼叫GetLastError()也没有最后的误差值自动重置为0,因此它是安全地调用两次.
编译器/运行时是否生成调用Win32 API函数的代码将由您的特定运行时决定.为了安全而不依赖于此,请使用双语句版本:
const string msg = error_message();
throw runtime_error(msg);
Run Code Online (Sandbox Code Playgroud)
更好的是,对于未来的代码读者,在GetLastError()外面打电话会很有用error_message():
const string msg = error_message(GetLastError());
throw runtime_error(msg);
Run Code Online (Sandbox Code Playgroud)
这样,读者将GetLastError()在相应的Win32 API调用之后立即看到该调用.
如果你看一下生成的汇编代码,就会清楚发生了什么.以下C++代码:
hDevice = CreateFileA(path, // drive to open
// etc...
);
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
throw runtime_error(error_message());
}
Run Code Online (Sandbox Code Playgroud)
生成一段汇编代码(至少使用默认优化):
call _CreateFileA@28 #
LEHE4:
sub esp, 28 #,
mov DWORD PTR [ebp-12], eax # hDevice, D.51673
cmp DWORD PTR [ebp-12], -1 # hDevice,
jne L5 #,
mov DWORD PTR [esp], 8 #,
call ___cxa_allocate_exception # // <--- this call is made between the
# // CreateFile() call and the
# // error_message() call
mov ebx, eax # D.50764,
lea eax, [ebp-16] # tmp66,
mov DWORD PTR [esp], eax #, tmp66
LEHB5:
call __Z13error_messagev #
Run Code Online (Sandbox Code Playgroud)
您会看到为调用___cxa_allocate_exception异常分配一些内存块的调用.该函数调用正在改变GetLastError()状态.
当C++代码看起来像:
hDevice = CreateFileA(path, // drive to open
// etc...
);
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
const string msg = error_message();
throw runtime_error(msg);
}
Run Code Online (Sandbox Code Playgroud)
然后你得到以下生成的程序集:
call _CreateFileA@28 #
sub esp, 28 #,
mov DWORD PTR [ebp-12], eax # hDevice, D.51674
cmp DWORD PTR [ebp-12], -1 # hDevice,
jne L5 #,
lea eax, [ebp-16] # tmp66,
mov DWORD PTR [esp], eax #, tmp66
call __Z13error_messagev #
LEHE4:
sub esp, 4 #,
mov DWORD PTR [esp], 8 #,
call ___cxa_allocate_exception # // <--- now this happens *after*
// error_message() has been called
Run Code Online (Sandbox Code Playgroud)
在失败的CreateFile()呼叫和呼叫之间不调用外部功能error_message().
这种问题是使用某些全局状态(例如GetLastError()或)进行错误处理的主要问题之一errno.
| 归档时间: |
|
| 查看次数: |
2798 次 |
| 最近记录: |