在这里的堆栈溢出(现在已经被那些幂函数清除)的扩展参数之后,出现了一个问题,即何时应该真正调用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;
}

很明显,“纯粹主义者”的方法总是有效的!然而,c++语言标准是否保证“正常”方法也能工作?(也就是说,可以确定GetLastError()作为sprintf的参数将是在测试SetConsoleWindowInfo()的返回值之后执行的第一个代码吗?)
注:请不要对代码的质量评价太苛刻!如我所说,这是对原来问题的改编。
编辑:一个更典型的情况(我经常在我的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>;
}

但同样,GetLastError()是唯一的非常量参数。

最佳答案

我将把这个问题分成两个独立的问题:
“普通代码”示例是否按预期工作?
是的,这个确切的代码将按预期工作。其他函数参数是内置类型,即使没有定义order函数参数的求值,它们都不能干扰GetLastError调用。
“普通代码”示例是调用GetLastError的正确方法吗?
它不是,即使运行此代码会产生预期的结果。其原因是使用GetLastError作为函数参数对其他函数参数引入了隐式约束,即它们不能有最后更改错误的副作用。这使得代码更容易出错,也更难维护。
因此,经验法则是在调用其他函数或创建/销毁对象之前,将最后一个错误值存储在某个变量中。

关于c++ - 使用GetLastError()的真正正确方法(时间)是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57760080/

10-09 16:29