1

私は Visual Studio 2013 で MSVC を使用しています。これは私がコンパイルしているコードです:

#include <iostream>
using namespace std;

void crash()
{
    cout << "crash?" << endl;
    system("PAUSE");
}

int main(int argc, char *argv[])
{
    atexit(crash);
    //while(true);
    return 0;
}

現在のやり方 - それは魅力のように機能します。プログラムを開始すると、クラッシュ関数に入り、一時停止し、キーを押すと、通常どおり終了します。すべてクール。ただし、while ループのコメントを外し、コンソールの [X] ボタンを使用して閉じると、endl 関数内でクラッシュが発生します。クラッシュの原因が _Ostr.widen() であることがわかりました。これは、MSVC が提供する endl 関数の実装です。

template<class _Elem,
    class _Traits> inline
    basic_ostream<_Elem, _Traits>&
        __CLRCALL_OR_CDECL endl(basic_ostream<_Elem, _Traits>& _Ostr)
    {   // insert newline and flush stream
    _Ostr.put(_Ostr.widen('\n'));
    _Ostr.flush();
    return (_Ostr);
    }

Ctrl+C を使用してプログラムを終了しても、同じ結果になります。どうすればこれを修正できますか?

4

1 に答える 1

1

私の疑惑は本当だったようです。私は次のようにコードを修正しました:

#include <iostream>
using namespace std;

#include <Windows.h>

void crash()
{
    printf("%i\n", GetCurrentThreadId());
    system("PAUSE");
}

int main()
{
    printf("%i\n", GetCurrentThreadId());

    atexit(crash);
    //while(true);

    return 0;
}

プログラムが正常に存在する場合、両方の printf() は同じスレッド ID を表示しますが、Ctrl+C または X ボタンを押すと、スレッド ID が異なります。これはクラッシュの説明であり、考えてみると非常に理にかなっています。したがって、この問題に対処する方法の小さな例を次に示します。

#include <iostream>
#include <conio.h>
using namespace std;

#include <Windows.h>

volatile bool wantClose = false;

void OnExit()
{
    cout << GetCurrentThreadId() << endl;
    system("PAUSE");
}

BOOL WINAPI OnConsoleClose(DWORD dwCtrlType)
{
    wantClose = true; // set a flag that the console wants us to close
    ExitThread(0); // kill this thread immediately so it doesn't make the console stuck
    return FALSE;
}

int main()
{
    cout << GetCurrentThreadId() << endl;

    SetConsoleCtrlHandler(OnConsoleClose, TRUE); // handle close requests from the console
    atexit(OnExit);
    while(!wantClose); // at some point in our code we will have to check whether the console wants us to close down

    return 0;
}

注意: system("PAUSE") の使用とビジー待機は、例を単純にするためだけのものです。実際のコードでの使用はお勧めしません。

于 2014-05-10T19:42:31.207 に答える