MFCは「User Breakpoint called from code at」エラーを再現――CStringがマルチスレッドで起こりやすい問題

2362 ワード

エラーを再現すると
最近、あるプロジェクトで「User Breakpoint called from code at」というエラーがよく発生しているため、このエラーは実行するたびに発生するのではなく、10分、数時間発生する場合があります.これはいったい何が原因なのでしょうか.
実行するたびにCStringクラスに関連し、またマルチスレッドプログラミングモードであるため、この状況をコピーしてエラーを再現しようとする.私はそうしました.
VC 6はダイアログモードに基づいて新しいプロジェクトを作成し、CCTestMutiThreadDlgのcppファイル内のすべての関数の外部にCStringクラスのグローバル変数とその変数を操作する3つのスレッド関数を作成します.
CString g_str;
UINT Proc1(LPVOID param)
{
	while(1)
		g_str = "FisrtThread";
	
	return 0;
}
UINT Proc2(LPVOID param)
{
	while(1)
		g_str = "SecondThread";
	return 0;
}
UINT Proc3(LPVOID param)
{
	while(1)
		g_str = "ThirdThread";
	return 0;
}

ダイアログボックスにボタンを追加し、ボタンの応答関数に次のコードを追加します.
	AfxBeginThread(Proc1,this);
	AfxBeginThread(Proc2,this);
	AfxBeginThread(Proc3,this);
	Sleep(100000);

その後プログラムを実行し、ダイアログボタンをクリックすると、上記のエラーメッセージがポップアップされます!
二修復エラー
上記のエラーは、マルチスレッドがグローバルCStringにアクセスした場合、CStringはスレッドセキュリティオブジェクトではないため、エラーが発生します.どのように変更しますか?スレッドを同期処理するのは明らかです.ここでは臨界領域の方法で同期を行った.
まず、CCTestMutiThreadDlgのcppファイルでグローバル臨界領域オブジェクトCRITICAL_を定義します.SECTION g_cs;
次に、ボタン応答関数でスレッドが開始する前に、臨界領域を初期化し、最後に削除します.
	InitializeCriticalSection(&g_cs);
	AfxBeginThread(Proc1,this);
	AfxBeginThread(Proc2,this);
	AfxBeginThread(Proc3,this);
	InitializeCriticalSection(&g_cs);
 	Sleep(100000);
	DeleteCriticalSection(&g_cs);
最後に各スレッドを同期
UINT Proc1(LPVOID param)
{
	while(1)
	{
		EnterCriticalSection(&g_cs);
		g_str = "FisrtThread";
		LeaveCriticalSection(&g_cs);
	}
	
	return 0;
}
以降にこのプログラムを実行すれば、問題はありません.
三延展
1グローバルのCStringオブジェクトをグローバルのintオブジェクトに変換した場合、上記の問題はありません
2各スレッドにSleep(100)を加える.関数、上記の問題はしばらく発生しません
3 Releaseバージョンで実行しても、問題ない!
また、ネット上には次のような言葉があります.
げんしょう
g_testがint,short charの場合,マルチスレッド交差読み書きエラーの問題は存在しないg_testはdouble,float,int 64の場合、マルチスレッドのクロスオーバー読み書きエラーの問題があり、_int 64は、付与値が0 xFFFF未満の場合はエラーが発生せず、0 xFFFFFFより大きい場合はエラーがg_testがCStringの時、交差読み書きの誤りが存在して、時にはプログラムが崩壊してまた:Sleep(1)機械カードをプラスしないで死んだことがあって、CPU占有率は100%に達して、4つの核心占有率はすべていっぱいで、マルチコア環境の下で運行することを保証することができます
結論
1.int,short,char,BOOLなど4バイト以下の単純なデータ型に対して、論理的な前後関係がなければ、マルチスレッド読み書きは完全にロック2をかけなくてもよい.floatが4バイトであるにもかかわらず、マルチスレッドアクセス時にはロック3が必要である.4バイトより大きい単純なタイプ、例えばdouble、int 64など、マルチスレッド読み書きにはロックが必要です.4.クラス、構造体、コンテナなど、すべての複雑なタイプにロックを付ける必要があります.
総合的に見ると、鍵をかければいいです.