[英]What is the REALLY correct way (time) to use GetLastError()?
在Stack Overflow(現在已被Powers-that-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;
}
顯然,“純粹主義”的方法總能正常運作! 但是, c++
語言標准是否保證“正常”方法也有效? (也就是說,可以確定作為sprintf
的參數的GetLastError()
將是在測試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>;
}
但同樣, GetLastError()
是唯一的非const參數。
我將這個問題分成兩個獨立的問題:
GetLastError
調用。 GetLastError
的正確方法嗎? GetLastError
作為函數參數會對其他函數參數引入隱式約束 ,它們必須沒有最后錯誤更改副作用。 這使得代碼更容易出錯並且更難以維護。 因此經驗法則是在調用其他函數或創建/銷毀對象之前將最后一個錯誤值存儲在某個變量中。
非純粹的方式在這里很好
在調用函數時(無論函數是否為內聯函數,以及是否使用了顯式函數調用語法),與任何參數表達式或指定被調用函數的后綴表達式相關聯的每個值計算和副作用都會被排序執行被調用函數體中的每個表達式或語句。
規則3 ,我認為這對應於C ++ 17標准草案版本中的§8.2.2.5。
在這種情況下,沒有任何其他副作用的論點。
但請注意,它很脆弱,如果有人做頑皮的事情
#define sprintf (log_call_to_sprintf(), sprintf)
你運氣不好
讓我們有下一個代碼片段
if (<WinApi call failed>) {
SomeApiCall(arg<1>, .., GetLastError(), .., arg<n>);
}
並假設下一個條件:
SomeApiCall
不是宏擴展到其他東西 - 這正是一些函數調用 arg<1>
... arg<n>
),除GetLastError()
,僅使用內部c / c ++語言表達式 ,無需任何外部函數調用(包括語言支持庫) 參數中沒有任何內容,什么可以導致硬件異常,如除以零,指針引用內存等
這不是關於編碼風格的問題
例如這個電話
SomeApiCall( "some text", GetLastError(), 8);
符合2和3
在這種情況下,我們可以說,在<WinApi call failed>
之后,可以在更改線程的最后錯誤代碼值之前調用GetLastError()
。 因為:
SomeApiCall
) 在執行被調用函數體內的每個表達式或語句之前計算 <WinApi call failed
>和SomeApiCall
只存在arg<1>
,.., GetLastError()
,.., arg<n>
<WinApi call failed
>和GetLastError()
調用 - 沒有任何windows api調用 <WinApi call failed
>和GetLastError()
調用之間不會更改最后錯誤代碼的結果值
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.