我可以在函数的第一行中启动`GetLastError`吗?

时间:2015-11-02 16:42:46

标签: c++ winapi

我知道发生错误时会立即调用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。这种使用方式是否可以接受?

4 个答案:

答案 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进行必要的验证检查(通常是与FALSE0进行比较的某个版本),并且在失败时立即调用::GetLastError()以获取异常的错误代码。

在这两种情况下,我都会在构建将要抛出的异常值时尝试使用::FormatMessage来获取有意义的错误消息字符串。

这些宏旨在用于您不希望API调用失败且失败确实非常特殊的情况。