我知道发生错误时会立即调用GetLastError
。我写了这个函数:
void PrintErrorMsg() {
DWORD errCode = GetLastError();
LPTSTR msg = NULL;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errCode, 0, (LPTSTR)&msg, 0, NULL);
wcerr << msg << endl;
HeapFree(GetProcessHeap(), 0, msg);
}
现在我在我的代码中使用它:
LPCTSTR boundaryName = L"BushmanBoundary";
HANDLE hBoundary = CreateBoundaryDescriptor(boundaryName, 0);
if (NULL == hBoundary) {
PrintErrorMsg();
}
所以我在GetLastError
函数的第一个代码行中调用了PrintErrorMsg
。这种使用方式是否可以接受?
答案 0 :(得分:2)
该代码没问题。返回CreateBoundaryDescriptor
和调用GetLastError
之间不会调用Windows API函数。
答案 1 :(得分:1)
调用线程执行的函数通过调用SetLastError函数设置该值。当函数的返回值指示此类调用将返回有用数据时,应立即调用GetLastError函数。这是因为有些函数在成功时调用SetLastError为零,消除了最近失败函数设置的错误代码。
您的代码没问题,因为您没有调用可能在失败和致电SetLastError()
之间拨打GetLastError()
的功能(例如Win32 API调用)。
请注意,插入运算符可以调用SetLastError()
。
std::cout << "Win32 function failed with error: " << GetLastError() << std::endl;
过去,我GetLastError()
无法返回正确的错误代码,因为它已由插入操作符设置/重置,因此被此类事件搞砸了。
答案 2 :(得分:0)
是的,这是允许的。我做了类似的事情,除了我将错误代码作为参数传递,但是将参数的默认值设为class A
var cachedPoints = NSCache()
func rAt(theta theta: CGFloat) -> CGFloat {
if let r = self.cachedPoints.objectForKey(theta) as? CGFloat {
return r
}
// do some very expensive maths here...
let r = self.veryExpensiveFunction(theta)
self.cachedPoints.setObject(r, forKey: theta)
return r
}
}
的结果,如下所示:
GetLastError()
它更灵活,对我来说效果很好。
答案 3 :(得分:0)
我发现处理Win32 API(或任何C风格API)的这些低级细节的最佳方法是立即将C风格的API提升到C ++实践中。我使用的一种方法是将C样式API调用包装在一个验证返回值的宏中,然后在返回值指示失败的情况下将相应的错误代码提取到异常中。
我的书Chapter 1的 "The Direct3D Graphics Pipeline"概述了COM HRESULT
返回值的这种方法。如果THR
表示失败,则抛出宏HRESULT
。在HRESULT
中,失败状态和错误代码包含在相同的整数值中,因此可以直接从提供的HRESULT
计算异常。在将要检查的值传递给检查失败的辅助函数之前,宏用__FILE__
和__LINE__
修饰其参数。如果检测到故障,则将所有信息收集到抛出的异常中。如果HRESULT
表示成功,则返回HRESULT
值。
我还为TWS
提供了Win32 API状态的类似变体。这会对Win32 API进行必要的验证检查(通常是与FALSE
或0
进行比较的某个版本),并且在失败时立即调用::GetLastError()
以获取异常的错误代码。
在这两种情况下,我都会在构建将要抛出的异常值时尝试使用::FormatMessage
来获取有意义的错误消息字符串。
这些宏旨在用于您不希望API调用失败且失败确实非常特殊的情况。