4

C++ コードから TerminateThread を呼び出すと、後で FatalExecutionEngineError MDA が発生します。このエラーは、主に、文字列に対してさまざまな操作 (つまり、連結) を行っているときに発生します。以下にリストされているコードは、それを再現する方法を示しています。

なぜそれが起こるのですか?どうすればそれを修正し、TerminateThread を引き続き使用できますか?

ありがとう

エラーは次のとおりです。

FatalExecutionEngineError was detected
Message: The runtime has encountered a fatal error. 
The address of the error was at 0x7880bb35, on thread 0x18f0. 
The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. 
Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

C++ コード:
Module.cpp:

#include "ThreadModule.h"
using namespace ThreadModule;

DWORD WINAPI workThread(LPVOID lpParam) {
    while(1) {
        System::Threading::Thread::Sleep(5);
        printf(".");
    }
    return 0;
}

bool Module::StartThread() {
    handle = CreateThread(
        NULL,
        0,
        workThread,
        NULL,
        0,
        &threadIdInput);
    return true;    
}

bool Module::StopThread() {
    TerminateThread(handle, 0);
    handle = NULL;
    return true;
}

C# コード:

static void Main(string[] args)
{
    Module module = new Module();

    module.StartThread();
    string s = "";
    for (int i = 0; i < 10000; i++)
    {
        s += i.ToString();
    }
    module.StopThread();
    s = "";
    for (int i = 0; i < 10000; i++)
    {
        s += i.ToString();  //After ~250 iteration get exception
    }
    Console.WriteLine("Completed!!");
}
4

1 に答える 1

4
   System::Threading::Thread::Sleep(5);

開始したスレッドは、ネイティブ C++ コードではなく、マネージ コードを実行しています。C++/CLI コードを記述できるように、/clr オプションを有効にしてこれをコンパイルしたことは明らかです。これは問題です。CLR はそのスレッドを認識しています。必然的に、ガベージ コレクターを実行して管理対象オブジェクトの参照を探すときに、スレッドのスタックを調べる必要があります。

これにより、TerminateThread() でスレッドを強制終了することが問題になります。これは、クリーンアップを実行しない危険な winapi 関数です。CLR は、デッド スレッドのスタックをスキャンするときにフォールオーバーします。

CLR は、Thread::Abort() を使用して安全なスレッド アボートを実行できます。それでもそうするのは良い考えではありませんが、少なくともプログラムをこれにひどく乗り込ませるつもりはありません。スレッドがネイティブ コードを実行している場合、Abort() は機能しないことに注意してください。スレッドを中止することが良い考えであるという考えを完全に書き留めるのが確かに最善です。

スレッドに適切に停止を求める明確な場所は、while(1) ステートメントです。

于 2013-03-05T20:14:13.340 に答える