エラーの定義と解決方法

エラーの定義

エラーに対処するには、まずその定義を明確にします。

分類 説明 検出者 検出タイミング
構文エラー
(syntax error)
言語の構文や規則に違反。 コンパイラ コンパイル時※1
リンカエラー
(linker error)
リンクの設定ミス。 リンカ リンク時
ランタイムエラー / 実行時エラー
(runtime error)
コンピュータが処理できない問題。

このエラーが発生すると、プログラムはOSによって強制終了させられます。

OS プログラム実行時
論理エラー
(logical error)
誤った結果の出力や、期待とは異なる動作。

このエラーはテスト ツールによって早期に発見できます。

プログラマ
※1 構文エラーは、IDEによってはコーディング時にも把握できます。

エラーの防止

言語や環境に応じた適切な方法を用いることで、効率的にエラーの原因を特定し、それに対処することができます。

警告レベルの設定

警告レベルを最高に設定しておくことで、問題になりそうなコードを事前に察知できます。たとえばMicrosoftのコンパイラ (cl.exe) では、/wオプションで警告レベルを設定できます。

デバッグの手法

言語ごとのデバッグ手法

OSごとのデバッグ手法

デバッグ ツール

環境ごとのデバッグ ツール

エラー発生時の処理

エラーが発生することを想定し、それに備えます。

例外処理 (Exception handling)

自身では対処できない問題に遭遇した関数は、呼び出し側のコードがそれに対処できることを期待して「例外」を投げます。例外処理とは、このようなエラー処理の仕組みを意味します。

投げられた例外を捕捉しない場合、プログラムはOSによって強制終了させられます。

言語ごとの例外処理

Windowsの構造化例外処理

対処法の提示

それがユーザーが対処可能な問題ならば、エラーメッセージとともに対処法を示します。その表示方法については、エラー メッセージ | MSDNで詳しくまとめられています。

環境ごとのエラー

Windows

GetLastError()

DWORD WINAPI GetLastError( void );
GetLastError 関数 (errhandlingapi.h) - Win32 apps | Microsoft Learn

呼び出したスレッドの、直近のエラーコードを取得できます。これで得られるコードの意味は、System Error Codes (Windows)のページで確認するか、strerror()で文字列として取得することで確認できます。

char* errMsg = strerror(GetLastError());
strerror、_strerror、_wcserror、__wcserror | Microsoft Learn

このときエラー番号が未知の場合には、"Unknown error"と返されます。strerror()を使用することにC4996で警告されるならば、代わりにstrerror_s()を用います。

char errMsg[0xFF];
strerror_s(errMsg, sizeof(errMsg), GetLastError());

これをより柔軟に取得するには、FormatMessage()を用います。 FormatMessage 関数 (winbase.h) - Win32 apps | Microsoft Learn c++ - How to get the error message from the error code returned by GetLastError()? - Stack Overflow

DWORD messageID = 1; // GetLastError();

LPSTR buffer = NULL;
size_t bufferSize = FormatMessageA(
    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,      // メッセージの定義場所
    messageID, // メッセージ識別子
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // メッセージの言語識別子。ユーザーの既定の言語
    (LPSTR)&buffer, // 文字列を受け取るバッファへのポインタ
    0,               // 出力バッファに割り当てる最小サイズ
    NULL); // 書式設定されたメッセージの挿入値として使用される値の配列

std::string message(buffer, bufferSize); // L"ファンクションが間違っています。\r\n"
LocalFree(buffer);

コンパイラ

参考

参考書

複数の技術系サイトから、まとめて検索