Ich habe eine Reihe von Exception-Klassen für Win32API und MFC, die den aktuellen Win32-Fehlercode (GetLastError()
) erfassen und formulieren eine menschenlesbare Nachricht, wo es aufgetreten ist.Welche Regeln gelten für die Standardzuordnung von Argumenten?
Ich verlasse mich auf die Fähigkeit, den aktuellen Fehlercode zu erfassen, bevor der ctor ihre Arbeit zu tun beginnt, unter der Annahme, dass die Argumente für den ctor sicher gelöst werden müssen, bevor der ctor aufgerufen wird.
Aber ich habe Probleme in meinem aktuellen Build, die Compilation Tooling von 120_xp auf 120 in VS2013 geschaltet (Ich bin nicht 100% sicher, dass dies die Quelle der Änderung ist - es könnte für einige Zeit ruhen unabhängig von der Änderung des Plattform-Toolsets).
Allerdings hätte ich gedacht, dass nichts davon relevant ist - dass C++ würde erfordern, dass alle Argumente zuerst aufgelöst werden, dann wird der Funktionsaufruf ausgeführt, so dass das Standardargument error
unten immer den aktuellen Fehlercode zuvor hätte die ctor Aufruf (die es möglicherweise ändern könnte):
CWin32APIErrorException::CWin32APIErrorException(const CString & source, const CString & api, DWORD error /*= GetLastError()*/)
: CContextException(FormatString(_T("In %s, %s() returned "), source, api), error)
, m_source(source)
, m_api(api)
{
}
Hier ist der Aufruf-Kontext:
m_file = CreateFile(filename, FILE_GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (!m_file) // NOTE: m_file is smart handle and it's operator bool() knows that the invalid file handle is "false"
throw CWin32APIErrorException(__FUNCTION__, _T("CreateFile"), GetLastError());
Wenn ich den Aufruf-Kontext die Erfassung des aktuellen Fehlercode zu zwingen, zu ändern, die ich in der Tat zu tun bekommen 2 Fehler:
m_file = CreateFile(filename, FILE_GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (!m_file)
{
auto error = GetLastError();
throw CWin32APIErrorException(__FUNCTION__, _T("CreateFile"), error);
}
FormatString
ist einfach, und es bewahrt den aktuellen Fehlercode:
CStringW FormatString(const wchar_t * format, ...)
{
const DWORD dwError = ::GetLastError();
va_list args;
va_start(args, format);
CStringW str;
str.FormatV(format, args);
::SetLastError(dwError);
return str;
}
Das Problem, das ich erlebt habe, ist, dass ich sehe Fehler 122: Puffer zu Systemaufruf zugeführt wird, zu klein. Der Fehlercode zum Aufrufen dieser Ausnahme lautet jedoch Fehler 2: Datei nicht gefunden.
Ich würde weit bevorzugen, dass meine Software-Bericht "Datei nicht gefunden", die richtiger und umsetzbar ist.
Also: 1. Bin ich falsch über C++ garantieren, dass alle Argumente gelöst werden, bevor der Funktionsaufruf (der Ctor) aufgerufen wird? 2. Wo sonst Anrufe gemacht werden könnten bekommen, dass der aktuellen Fehlercode (CString Ctor (n) sind die einzigen sind andere Dinge vor dem CWin32APIErrorException::CWin32APIErrorException()
Ctor aufgerufen ändern könnte.
Was bedeutet, dass CString Ctor offenbar die aktuellen Fehler zu ändern? ! igitt
Kann mir jemand mitteilen, wo ich in meinem Verständnis falsch bin
Danke
Die Reihenfolge der Parameterauswertung nicht spezifiziert ist, also ja, die CString Konstruktor kann in die Quere kommen. –
Danke Raymond. Ich hatte nur eine Ahnung - und es stellt sich heraus, dass wir, weil wir Unicode kompilieren - die '__FUNCTION__' in eine breite Zeichenfolge im CString ctor konvertiert wird, was etwas auslöst, das intern zum Fehler 122 führt. :( – Mordachai
Dies wäre relativ einfach zu beheben. Sie übergeben String-Literale an den Konstruktor, so dass es keine 'CString'-Parameter benötigen. Verwenden Sie einfach' LPCTSTR'. (Verwenden Sie den Präprozessor, um das Makro '__FUNCTION__' in eine umzuwandeln wide string.) Das löst das Problem, dass beliebiger Code ausgeführt wird, um die Parameter zu konstruieren. Haben Sie andere Aufrufkontexte, in denen dynamisch generierte Strings übergeben werden müssen? –