在这里对Stack Overflow(现在已经被Powers-be-Be清除)进行了扩展讨论之后,出现了一个问题:何时应该真正调用该GetLastError
函数。
注意:这不是关于样式的问题,而只是关于:(a)在“非纯粹”代码的情况下,标准保证(或不保证)什么?(b)就安全winapi
编程而言,什么是“最佳实践”?
这是一个示例(改编自上面发布的原始问题):
#include <windows.h>
#include <stdio.h>
#include <iostream>
//#define PURIST 1
using namespace std;
int main()
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SMALL_RECT wSize = { 0,0,60,20 }; // Works on my screen!
if (hConsole == nullptr) {
cout << "Console Handle is Null" << endl;
return 1;
}
else {
char message[256];
if (!SetConsoleWindowInfo(hConsole, TRUE, &wSize)) {
#ifdef PURIST
// 'Purist' code ...
DWORD eCode = GetLastError();
sprintf(message, "SetConsoleWindowInfo failed; code = %d!", eCode);
#else
// More normal code ...
sprintf(message, "SetConsoleWindowInfo failed; code = %d!", GetLastError());
#endif
}
else {
strcpy(message, "SetConsoleWindowInfo call succeeded!");
}
cout << message << endl;
}
getchar(); // Just to stop console closing!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
显然,“纯粹”方法将始终正常工作!但是,c++
语言标准是否保证“正常”方法也将起作用?(也就是说,可以确定GetLastError()
作为参数to sprintf
将是测试返回值之后执行的第一个代码SetConsoleWindowInfo()
)
PS:请不要对我的代码质量太苛刻!正如我所说,这是对原始问题的改编。
编辑:一种更典型的情况(我在Windows应用程序中使用了很多)看起来像这样:
if (<WinApi call failed>) {
TCHAR eText[256];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(), 0, eText, 255, nullptr);
// Do something with eText, etc. ...
return <error code>;
}
Run Code Online (Sandbox Code Playgroud)
但是,这GetLastError()
也是唯一的非常量参数。
我将把这个问题分为两个独立的问题:
GetLastError
调用。GetLastError
吗?GetLastError
as函数参数对其他函数参数引入了隐式约束,即它们必须没有改变最终错误的副作用。这使得代码更容易出错,并且更难以维护。因此,经验法则是在调用其他函数或创建/销毁对象之前,将最后的错误值存储在某个变量中。