Following an extended argument here on Stack Overflow (which has now been cleaned up by the Powers-that-Be), the question has arisen as to when one should really call the GetLastError
function.
Note: This is not a question about style, just about: (a) what the standard guarantees (or not) in the case of the 'non-purist' code; (b) in terms of safe winapi
programming, what is the 'best practice'.
Here's an example (adapted from the original question there posted):
#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;
}
Obviously, the 'purist' approach will always work properly! However, does the c++
language standard guarantee that the 'normal' approach will also work? (That is, can one be sure that GetLastError()
as an argument to sprintf
will be the first code to execute after testing the return value of SetConsoleWindowInfo()
?)
PS: Please don't judge me too harshly on the quality of the code! As I said, it is an adaptation of the original question.
EDIT: A more typical situation (that I use a lot in my Windows apps) looks like this:
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>;
}
But again, GetLastError()
is the only non-const argument.
I will separate this question into two independent questions:
GetLastError
invocation. GetLastError
? GetLastError
as function argument introduces implicit constraint on other function arguments that they must have no last-error changing side effects. This makes code more error prone and more difficult to maintain. So the Rule of thumb would be to store last error value in some variable prior to calling other functions or creating / destroying objects.
The non-purist way is fine here
When calling a function (whether or not the function is inline, and whether or not explicit function call syntax is used), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.
Rule 3 , I think this corresponds to §8.2.2.5 in the draft version of the C++17 standard.
And in this case there aren't any other arguments with side-effects.
But note that it's fragile, and if someone does something naughty like
#define sprintf (log_call_to_sprintf(), sprintf)
you're out of luck.
let we have next code snippet
if (<WinApi call failed>) {
SomeApiCall(arg<1>, .., GetLastError(), .., arg<n>);
}
and assume next conditions:
SomeApiCall
not a macro expanded to something else - this is exactly some function call arg<1>
... arg<n>
), except GetLastError()
, used only internal c/c++ language expressions , which calculated without any external functions calls (including language support libraries) nothing exist in arguments, what can lead to hardware exception, like divide by zero, reference memory by pointer, etc
this not question about coding style
for example this call
SomeApiCall( "some text", GetLastError(), 8);
conform to 2 and 3
in this case we can say that GetLastError()
will be called before thread's last-error code value can be changed, after <WinApi call failed>
. because:
SomeApiCall
) calculated before execution of every expression or statement in the body of the called function <WinApi call failed
> and SomeApiCall
exist only arg<1>
, .., GetLastError()
, .., arg<n>
<WinApi call failed
> and GetLastError()
call - no any windows api calls <WinApi call failed
> and GetLastError()
call
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.