关于创建的线程执行完就崩溃的问题

yimao_44 2014-01-17 10:10:13
我的程序有个要求,就是当按下某个按钮之后启动新进程,在新进程中安排一些操作等
的新进程弄好的 但是执行完毕的时候总是自己死在了一个系统函数


inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
EnterCriticalSection(&m_sect);
ASSERT(nSlot != 0 && nSlot < m_nMax);
ASSERT(m_pSlotData != NULL);
ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);
ASSERT(m_tlsIndex != (DWORD)-1);
if( nSlot <= 0 || nSlot >= m_nMax ) // check for retail builds.
{
LeaveCriticalSection(&m_sect);
return NULL;
}

CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);
if (pData == NULL || nSlot >= pData->nCount)
{
LeaveCriticalSection(&m_sect);
return NULL;
}
void* pRetVal = pData->pData[nSlot];
LeaveCriticalSection(&m_sect);
return pRetVal;
}



死在上面的 void* pRetVal = pData->pData[nSlot];
LeaveCriticalSection(&m_sect); 这块了

我的创建代码如下


void CBuildImageLibDlg::OnBnClickedButtonRecog()
{
// TODO: Add your control notification handler code here
m_pThrd = AfxBeginThread(RecogFunc,this,NULL,0,0,NULL);
if( m_pThrd!= NULL)
{
m_ThreadHandle = m_pThrd->m_hThread;
CloseHandle(m_ThreadHandle);
}

}


...全文
289 点赞 收藏 9
写回复
9 条回复
w_xei 2014年01月17日
1、楼上说的正确,不要在工作线程中直接操作UI,应该使用消息机制操作UI;但这不应该是程序崩溃的原因 2、你在主线程中调用CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex); 没在线程函数中看到你使用LocalAlloc分配线程局部内存,使用TlsSetValue设置内存,所以没办法判断问题所在。初步估计是TlsGetValue取到的void*内存指针在强制转换成CThreadData*后,再访问时出错,应该是你取到的不是你希望要得到的地址,再访问时就会发生越界。这种多线程的内存访问需要多加注意。
回复 点赞
见习学术士 2014年01月17日
引用 5 楼 u012162828 的回复:


UINT RecogFunc(LPVOID pParam)
{
	CBuildImageLibDlg * pDlg = (CBuildImageLibDlg *)pParam;
	if (pDlg->m_vecPath.size() <= 0)
	{
		::MessageBox(pDlg->m_hWnd, _T("请先加载图像!"), _T("提示"), MB_OK);
		return 0;;
	}

	TCHAR szPath[MAX_PATH];
	GetModuleFileName(AfxGetInstanceHandle(), szPath, MAX_PATH);
	CString strDir(szPath);
	strDir = strDir.Left(strDir.ReverseFind('\\')+1);
	SetCurrentDirectory(strDir);
	strDir += _T("TH-ImageOCR.dll");
	HINSTANCE Hins = LoadLibrary(strDir);
	if (Hins == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pInfoInit InfoInit = (pInfoInit)GetProcAddress(Hins, "WT_InfoInit");
	if (InfoInit == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pExtractInfo ExtractInfo = (pExtractInfo)GetProcAddress(Hins, "WT_ExtractInfo");
	if (ExtractInfo == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pExtractInfoEx ExtractInfoEx = (pExtractInfoEx)GetProcAddress(Hins, "WT_ExtractInfoEx");
	if (ExtractInfoEx == NULL)
	{
		int err = GetLastError();
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pInfoRelease InfoRelease = (pInfoRelease)GetProcAddress(Hins, "WT_InfoRelease");
	if (InfoRelease == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pWT_GetError GetError = (pWT_GetError)GetProcAddress(Hins, "WT_GetError");
	if (GetError == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pWT_SetRecogRect SetRecogRect = (pWT_SetRecogRect)GetProcAddress(Hins, "WT_SetRecogRect");
	if (SetRecogRect == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}
	CString strPath;
	pDlg->GetDlgItem(IDC_EDIT_PATH)->GetWindowText(strPath);

	CDC *pDC = pDlg->GetDC();
	pDC->SetBkMode(TRANSPARENT);

	LOGFONT logfont;
	memset(&logfont, 0x0, sizeof(logfont));
	logfont.lfHeight = 13;
	logfont.lfWeight = FW_NORMAL;
	logfont.lfCharSet = GB2312_CHARSET;
	wcscpy_s(logfont.lfFaceName, _T("宋体"));
	CFont font;
	font.CreateFontIndirect(&logfont);
	CFont* poldFont = pDC->SelectObject(&font);
	pDC->SetTextColor(RGB(21, 106, 161));

	if (InfoInit(0x11,0x1,true))
	{
		pDlg->m_pShowView->GetSelectRect();
		USES_CONVERSION;
		for (vector<CString>::iterator iter=pDlg->m_vecPath.begin(); iter!=pDlg->m_vecPath.end(); ++iter)
		{
			if (!pDlg->m_pShowView->m_rcSelect.IsRectEmpty())
			{
				SetRecogRect(pDlg->m_pShowView->m_rcSelect.left, pDlg->m_pShowView->m_rcSelect.top, pDlg->m_pShowView->m_rcSelect.Width(), pDlg->m_pShowView->m_rcSelect.Height());
			}
			XTextInfo* pInfo = NULL;
			CString strTemp(strPath);
			strTemp += _T("\\");
			strTemp += *iter;

			CString strOut;
			strOut.Format(_T("正在识别:%s"), *iter);
			pDlg->m_strStatus = strOut;
			pDC->FillSolidRect(pDlg->m_rcStatus, 0xf7f7f7);
			if (!pDlg->m_strStatus.IsEmpty())
			{
				pDC->DrawText(pDlg->m_strStatus, pDlg->m_rcStatus, DT_LEFT);
			}
			pInfo = ExtractInfoEx(W2A(strTemp));
			int nErr = GetError();
			if (pInfo == NULL && nErr != 0)
			{
				::MessageBox(pDlg->m_hWnd, _T("解析错误!"), _T("提示"), MB_OK);
				FreeLibrary(Hins);
				pDC->SelectObject(poldFont);
				font.DeleteObject();
				pDlg->ReleaseDC(pDC);
				InfoRelease();
				pDlg->GetInfoFromOutput(NULL);
				return 0;
			}
			else if (pInfo == NULL && nErr == 0)
			{
				pDlg->GetInfoFromOutput(NULL);
				// 				strTemp = strTemp.Left(strTemp.ReverseFind('.')+1) + _T("txt");
				// 				if (!SaveInfoToTxt(strTemp))
				// 				{
				// 					
				// 					//Invalidate(FALSE);
				// 					//FreeLibrary(Hins);
				// 					//return;
				// 				}
			}
			else
			{
				pDlg->GetInfoFromOutput(pInfo);
				// 				strTemp = strTemp.Left(strTemp.ReverseFind('.')+1) + _T("txt");
				// 				if (!SaveInfoToTxt(strTemp))
				// 				{
				// 					//Invalidate(FALSE);
				// 					//FreeLibrary(Hins);
				// 					//return;
				// 				}

			}
			InfoRelease();
			strOut.Format(_T("正在释放:%s"), *iter);
			pDlg->m_strStatus = strOut;
			pDC->FillSolidRect(pDlg->m_rcStatus, 0xf7f7f7);
			if (!pDlg->m_strStatus.IsEmpty())
			{
				pDC->DrawText(pDlg->m_strStatus, pDlg->m_rcStatus, DT_LEFT);
			}

			pDlg->m_strStatus.Empty();
			pDC->FillSolidRect(pDlg->m_rcStatus, 0xf7f7f7);
		}
	}
	else
	{
		::MessageBox(NULL, _T("初始化失败!"), _T("提示"), MB_OK);
		FreeLibrary(Hins);
		pDC->SelectObject(poldFont);
		font.DeleteObject();
		pDlg->ReleaseDC(pDC);
		return 0;
	}
	pDC->SelectObject(poldFont);
	font.DeleteObject();
	pDlg->ReleaseDC(pDC);
	::MessageBox(NULL, _T("完成!"), _T("提示"), MB_OK);
	if (pDlg->m_nSelect >= 0)
	{
		CString strPath;
		pDlg->GetDlgItem(IDC_EDIT_PATH)->GetWindowText(strPath);
		strPath += _T("\\");
		strPath += pDlg->m_vecPath[pDlg->m_nSelect];
		if (GetFileAttributes(strPath) == 0xffffffff)
		{
			//m_pTextDraw->CleanStringVector();
			pDlg->GetDlgItem(IDC_EDIT_RESULT)->SetWindowText(_T(""));
			::MessageBox(NULL, _T("文件缺失,请重新识别并加载"), _T("提示"), MB_OK);
			return 0;
		}
		if (pDlg->m_pShowView->m_imgShow.IsNull())
		{
			pDlg->m_pShowView->LoadImage(strPath);
		}
		else
		{
			pDlg->m_pShowView->m_imgShow.Destroy();
			pDlg->m_pShowView->LoadImage(strPath);

		}

		if (pDlg->m_vecList.size() > pDlg->m_nSelect)
		{
			//m_pTextDraw->CleanStringVector();
			pDlg->GetDlgItem(IDC_EDIT_RESULT)->SetWindowText(_T(""));
			CString textTemp ;
			vector<LineInfo> *vecInfoTemp = &pDlg->m_vecList[pDlg->m_nSelect];
			for(vector<LineInfo>::iterator iter=vecInfoTemp->begin();iter!=vecInfoTemp->end();++iter)
			{
				if(iter==vecInfoTemp->begin())
				{
					textTemp = iter->strChars;
				}
				else
				{
					textTemp += _T("\r\n");
					textTemp += iter->strChars;
				}
			}
			pDlg->GetDlgItem(IDC_EDIT_RESULT)->SetWindowText(textTemp);
			//m_pTextDraw->SetVectorInfo(&m_vecList[m_nSelect]);
			pDlg->m_pShowView->m_vecLine = &pDlg->m_vecList[pDlg->m_nSelect];
		}

	}
	//pDlg->Invalidate(FALSE);
	FreeLibrary(Hins);
	return 0;
	
}

线程函数
线程函数创建完线程还没有退出,所以不应该这么快关闭句柄。 你的这个问题应该是线程函数中调用 W2A 导致,如果m_vecPath 这个容器很大的话,W2A在频繁调用的时候会出现问题,导致的栈内存耗尽,所以保险的方式是用在频繁调用时用{}把w2a包起来,这样一退出就自动释放资源,所以你只要将 W2A 封装到一个函数里面调用,那就可以解决这个问题
回复 点赞
yimao_44 2014年01月17日
引用 6 楼 VisualEleven 的回复:
线程函数中不要直接操作UI上的控件
为啥了 那你的意思是我把这个线程函数进行分割 一部分放在线程里面 一部分放在线程外面
回复 点赞
Eleven 2014年01月17日
线程函数中不要直接操作UI上的控件
回复 点赞
yimao_44 2014年01月17日


UINT RecogFunc(LPVOID pParam)
{
	CBuildImageLibDlg * pDlg = (CBuildImageLibDlg *)pParam;
	if (pDlg->m_vecPath.size() <= 0)
	{
		::MessageBox(pDlg->m_hWnd, _T("请先加载图像!"), _T("提示"), MB_OK);
		return 0;;
	}

	TCHAR szPath[MAX_PATH];
	GetModuleFileName(AfxGetInstanceHandle(), szPath, MAX_PATH);
	CString strDir(szPath);
	strDir = strDir.Left(strDir.ReverseFind('\\')+1);
	SetCurrentDirectory(strDir);
	strDir += _T("TH-ImageOCR.dll");
	HINSTANCE Hins = LoadLibrary(strDir);
	if (Hins == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pInfoInit InfoInit = (pInfoInit)GetProcAddress(Hins, "WT_InfoInit");
	if (InfoInit == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pExtractInfo ExtractInfo = (pExtractInfo)GetProcAddress(Hins, "WT_ExtractInfo");
	if (ExtractInfo == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pExtractInfoEx ExtractInfoEx = (pExtractInfoEx)GetProcAddress(Hins, "WT_ExtractInfoEx");
	if (ExtractInfoEx == NULL)
	{
		int err = GetLastError();
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pInfoRelease InfoRelease = (pInfoRelease)GetProcAddress(Hins, "WT_InfoRelease");
	if (InfoRelease == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pWT_GetError GetError = (pWT_GetError)GetProcAddress(Hins, "WT_GetError");
	if (GetError == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}

	pWT_SetRecogRect SetRecogRect = (pWT_SetRecogRect)GetProcAddress(Hins, "WT_SetRecogRect");
	if (SetRecogRect == NULL)
	{
		::MessageBox(pDlg->m_hWnd, _T("加载识别库失败!初始化失败!"), _T("提示"), MB_OK);
		return 0;
	}
	CString strPath;
	pDlg->GetDlgItem(IDC_EDIT_PATH)->GetWindowText(strPath);

	CDC *pDC = pDlg->GetDC();
	pDC->SetBkMode(TRANSPARENT);

	LOGFONT logfont;
	memset(&logfont, 0x0, sizeof(logfont));
	logfont.lfHeight = 13;
	logfont.lfWeight = FW_NORMAL;
	logfont.lfCharSet = GB2312_CHARSET;
	wcscpy_s(logfont.lfFaceName, _T("宋体"));
	CFont font;
	font.CreateFontIndirect(&logfont);
	CFont* poldFont = pDC->SelectObject(&font);
	pDC->SetTextColor(RGB(21, 106, 161));

	if (InfoInit(0x11,0x1,true))
	{
		pDlg->m_pShowView->GetSelectRect();
		USES_CONVERSION;
		for (vector<CString>::iterator iter=pDlg->m_vecPath.begin(); iter!=pDlg->m_vecPath.end(); ++iter)
		{
			if (!pDlg->m_pShowView->m_rcSelect.IsRectEmpty())
			{
				SetRecogRect(pDlg->m_pShowView->m_rcSelect.left, pDlg->m_pShowView->m_rcSelect.top, pDlg->m_pShowView->m_rcSelect.Width(), pDlg->m_pShowView->m_rcSelect.Height());
			}
			XTextInfo* pInfo = NULL;
			CString strTemp(strPath);
			strTemp += _T("\\");
			strTemp += *iter;

			CString strOut;
			strOut.Format(_T("正在识别:%s"), *iter);
			pDlg->m_strStatus = strOut;
			pDC->FillSolidRect(pDlg->m_rcStatus, 0xf7f7f7);
			if (!pDlg->m_strStatus.IsEmpty())
			{
				pDC->DrawText(pDlg->m_strStatus, pDlg->m_rcStatus, DT_LEFT);
			}
			pInfo = ExtractInfoEx(W2A(strTemp));
			int nErr = GetError();
			if (pInfo == NULL && nErr != 0)
			{
				::MessageBox(pDlg->m_hWnd, _T("解析错误!"), _T("提示"), MB_OK);
				FreeLibrary(Hins);
				pDC->SelectObject(poldFont);
				font.DeleteObject();
				pDlg->ReleaseDC(pDC);
				InfoRelease();
				pDlg->GetInfoFromOutput(NULL);
				return 0;
			}
			else if (pInfo == NULL && nErr == 0)
			{
				pDlg->GetInfoFromOutput(NULL);
				// 				strTemp = strTemp.Left(strTemp.ReverseFind('.')+1) + _T("txt");
				// 				if (!SaveInfoToTxt(strTemp))
				// 				{
				// 					
				// 					//Invalidate(FALSE);
				// 					//FreeLibrary(Hins);
				// 					//return;
				// 				}
			}
			else
			{
				pDlg->GetInfoFromOutput(pInfo);
				// 				strTemp = strTemp.Left(strTemp.ReverseFind('.')+1) + _T("txt");
				// 				if (!SaveInfoToTxt(strTemp))
				// 				{
				// 					//Invalidate(FALSE);
				// 					//FreeLibrary(Hins);
				// 					//return;
				// 				}

			}
			InfoRelease();
			strOut.Format(_T("正在释放:%s"), *iter);
			pDlg->m_strStatus = strOut;
			pDC->FillSolidRect(pDlg->m_rcStatus, 0xf7f7f7);
			if (!pDlg->m_strStatus.IsEmpty())
			{
				pDC->DrawText(pDlg->m_strStatus, pDlg->m_rcStatus, DT_LEFT);
			}

			pDlg->m_strStatus.Empty();
			pDC->FillSolidRect(pDlg->m_rcStatus, 0xf7f7f7);
		}
	}
	else
	{
		::MessageBox(NULL, _T("初始化失败!"), _T("提示"), MB_OK);
		FreeLibrary(Hins);
		pDC->SelectObject(poldFont);
		font.DeleteObject();
		pDlg->ReleaseDC(pDC);
		return 0;
	}
	pDC->SelectObject(poldFont);
	font.DeleteObject();
	pDlg->ReleaseDC(pDC);
	::MessageBox(NULL, _T("完成!"), _T("提示"), MB_OK);
	if (pDlg->m_nSelect >= 0)
	{
		CString strPath;
		pDlg->GetDlgItem(IDC_EDIT_PATH)->GetWindowText(strPath);
		strPath += _T("\\");
		strPath += pDlg->m_vecPath[pDlg->m_nSelect];
		if (GetFileAttributes(strPath) == 0xffffffff)
		{
			//m_pTextDraw->CleanStringVector();
			pDlg->GetDlgItem(IDC_EDIT_RESULT)->SetWindowText(_T(""));
			::MessageBox(NULL, _T("文件缺失,请重新识别并加载"), _T("提示"), MB_OK);
			return 0;
		}
		if (pDlg->m_pShowView->m_imgShow.IsNull())
		{
			pDlg->m_pShowView->LoadImage(strPath);
		}
		else
		{
			pDlg->m_pShowView->m_imgShow.Destroy();
			pDlg->m_pShowView->LoadImage(strPath);

		}

		if (pDlg->m_vecList.size() > pDlg->m_nSelect)
		{
			//m_pTextDraw->CleanStringVector();
			pDlg->GetDlgItem(IDC_EDIT_RESULT)->SetWindowText(_T(""));
			CString textTemp ;
			vector<LineInfo> *vecInfoTemp = &pDlg->m_vecList[pDlg->m_nSelect];
			for(vector<LineInfo>::iterator iter=vecInfoTemp->begin();iter!=vecInfoTemp->end();++iter)
			{
				if(iter==vecInfoTemp->begin())
				{
					textTemp = iter->strChars;
				}
				else
				{
					textTemp += _T("\r\n");
					textTemp += iter->strChars;
				}
			}
			pDlg->GetDlgItem(IDC_EDIT_RESULT)->SetWindowText(textTemp);
			//m_pTextDraw->SetVectorInfo(&m_vecList[m_nSelect]);
			pDlg->m_pShowView->m_vecLine = &pDlg->m_vecList[pDlg->m_nSelect];
		}

	}
	//pDlg->Invalidate(FALSE);
	FreeLibrary(Hins);
	return 0;
	
}

线程函数
回复 点赞
yimao_44 2014年01月17日

xiug修改了放在析构函数里面还是有问题
回复 点赞
w_xei 2014年01月17日
应该不是楼上说的句柄的问题,把你的线程函数代码贴出来看,估计是内存访问冲突的问题吧!
回复 点赞
yimao_44 2014年01月17日
引用 1 楼 xiaoc1026 的回复:

void CBuildImageLibDlg::OnBnClickedButtonRecog()
{
    // TODO: Add your control notification handler code here
    m_pThrd = AfxBeginThread(RecogFunc,this,NULL,0,0,NULL);
    if( m_pThrd!= NULL)
    {
        m_ThreadHandle = m_pThrd->m_hThread;
        //不要这么快关闭句柄,你的线程还在运行!可以在对话框的析构函数里面关闭句柄
        //CloseHandle(m_ThreadHandle);
    }
 
}
可是线程函数执行结束的时候线程不就停止了吗
回复 点赞
见习学术士 2014年01月17日

void CBuildImageLibDlg::OnBnClickedButtonRecog()
{
    // TODO: Add your control notification handler code here
    m_pThrd = AfxBeginThread(RecogFunc,this,NULL,0,0,NULL);
    if( m_pThrd!= NULL)
    {
        m_ThreadHandle = m_pThrd->m_hThread;
        //不要这么快关闭句柄,你的线程还在运行!可以在对话框的析构函数里面关闭句柄
        //CloseHandle(m_ThreadHandle);
    }
 
}
回复 点赞
发动态
发帖子
进程/线程/DLL
创建于2007-09-28

6376

社区成员

4.9w+

社区内容

VC/MFC 进程/线程/DLL
社区公告
暂无公告