最近刚接触MFC,在调试项目的时候,点击退出时总会触发一个断点,如果直接运行exe(无论是debug还是release)都没有问题。
设置断点发现是在GdiplusShutdown(m_pGdiToken);处触发的的断点。
basic::basic()
{
GdiplusStartup(&m_pGdiToken, &m_gdiplusStartupInput, NULL);
}
basic::~basic()
{
GdiplusShutdown(m_pGdiToken);
}
查看相关代码始终没有找到,触发断点原因,相关代码如下:
bool ui::img_from_res(UINT nID, LPCTSTR sTR, Image * &pImg)
{
HINSTANCE hInst = AfxGetResourceHandle();
HRSRC hRsrc = ::FindResource (hInst, MAKEINTRESOURCE(nID), sTR); // type
if (!hRsrc)
return false;
// load resource into memory
DWORD len = SizeofResource(hInst, hRsrc);
BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);
if (!lpRsrc)
return false;
// Allocate global memory on which to create stream
HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
memcpy(pmem,lpRsrc,len);
IStream* pstm;
CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
// load from stream
pImg = Gdiplus::Image::FromStream(pstm);
// free/release stuff
GlobalUnlock(m_hMem);
pstm->Release();
FreeResource(lpRsrc);
return true;
}
DWORD ui::gifproc(LPVOID lpParam)
{
Image *img = (Image *)lpParam;
UINT nCount = img->GetFrameDimensionsCount();
GUID* pDimensionsIDs = (GUID*)new GUID[nCount];
img->GetFrameDimensionsList(pDimensionsIDs,nCount);
wchar_t strGUID[39]={0};
StringFromGUID2(pDimensionsIDs[0], strGUID, 39);
UINT nFrameCount = img->GetFrameCount(&pDimensionsIDs[0]);
delete[] pDimensionsIDs;
int size = img->GetPropertyItemSize(PropertyTagFrameDelay);
byte *p = new byte[size];
PropertyItem* pItem = (PropertyItem*)p;
img->GetPropertyItem(PropertyTagFrameDelay,size, pItem);
int fcount = 0;
GUID guid = FrameDimensionTime;
HDC hDC = ::GetDC(m_gifwnd);
Graphics gc(hDC);
RECT rect = {0};
GetClientRect(m_gifwnd, &rect);
int x = (rect.right - img->GetWidth()) / 2;
int y = (rect.bottom - img->GetHeight()) / 2;
while (m_gifruning)
{
gc.DrawImage(img, x, y, img->GetWidth(), img->GetHeight());
img->SelectActiveFrame(&guid, fcount++);
if (fcount == nFrameCount)
{
fcount = 0;
}
//long pause = ((long*)pItem->value)[fcount];
//Sleep(pause);
}
::ReleaseDC(m_gifwnd, hDC);
delete []p;
return 0;
}
void ui::bitmap_ex(HDC hDC, HBITMAP hbitmap, int x, int y, int w, int h, int hv)
{
if (hDC != NULL && hbitmap != NULL)
{
if (hv == 0)
{
BITMAP bmp;
HDC hMM = CreateCompatibleDC(hDC);
GetObject(hbitmap, sizeof(BITMAP), &bmp);
SelectObject(hMM, hbitmap);
SetStretchBltMode(hDC, HALFTONE);
StretchBlt(hDC, x, y, w, h, hMM, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
DeleteObject(hbitmap);
DeleteObject(hMM);
}
else
{
Graphics gr(hDC);
Bitmap bitmap(hbitmap, NULL);
if (hv == 1)
{
Point HoPoints[] = {Point(x + w, y), Point(x, y), Point(x + w, y + h)};
gr.DrawImage(&bitmap, HoPoints, 3);
}
else if (hv == 2)
{
Point VePoints[] = {Point(x, y + h), Point(x + w, y + h), Point(x, y)};
gr.DrawImage(&bitmap, VePoints, 3);
}
}
}
}
求大神指点一下。
主程序退出前,确保子线程已经退出。否则可能存在资源冲突,比如主线程退出了,资源释放了,但子线程还在使用该资源
报错的地方是在mov附近,要么是数组越界了,要么是指针失效了,访问了不能访问的地址。在你代码中,指针失效后仍在使用的可能性是最大的。在MFC中,子窗口或者bitmap这些资源在绘制的时候,使用的是系统分配给程序的资源(如DC),所以在调用GdiplusShutdown前,需要确保已经释放这些资源(如bitmap* 、Gdiplus::Graphics),或者关闭子窗口(或者结束绘制过程)。因为实在析构函数中报错,所以直接运行exe的时候,错误可能不会提示。
现在排查到问题可能出在time_proc(HWND hwnd, UINT id, UINT_PTR, DWORD)函数,
void kernel::begin(HWND hwnd)
{
m_f2f = 0;
m_mainwnd = hwnd;
m_test = test_ready;
if (!sqlite_open())
::MessageBox(_kernel.m_mainwnd, "打开数据库失败", "信息", MB_OK);
memset(&m_id, 0, sizeof(m_id));
memset(&m_drive, 0, sizeof(m_drive));
memset(&m_config, 0, sizeof(m_config));
_kernel.sqlite_db("select * from config", &m_config);
_kernel.sqlite_db("select * from through", &m_through);
char buf[MAX_PATH] = {0};
char sztime[MAX_PATH] = {0};
basic::get_time(sztime);
sztime[10] = '\0';
sprintf(buf, "select * from student where time = '%s'", sztime);
_kernel.sqlite_db(buf, &m_student);
ui::gif(GetDesktopWindow(), IDR_LOADING, true);
SetTimer(m_mainwnd, 1, 1000, time_proc);
_kernel.m_tmain.begin(main_proc);
}
在调用GdiplusShutdown(m_pGdiToken);时可能有资源没有释放
void kernel::time_proc(HWND hwnd, UINT id, UINT_PTR, DWORD)
{
if (_kernel.m_drive.idreadr && _kernel.m_drive.camera && _kernel.m_drive.network && _kernel.m_drive.gate)
{
KillTimer(hwnd, id);
return;
}
HDC hDC = ::GetDC(_kernel.m_mainwnd);
HBITMAP ha = LoadBitmap(AfxGetApp()->m_hInstance, (LPCSTR)IDB_A);
HBITMAP hb = LoadBitmap(AfxGetApp()->m_hInstance, (LPCSTR)IDB_B);
HBITMAP hc = LoadBitmap(AfxGetApp()->m_hInstance, (LPCSTR)IDB_C);
HBITMAP hd = LoadBitmap(AfxGetApp()->m_hInstance, (LPCSTR)IDB_D);
if (_kernel.m_drive.idreadr == false)
{
if (_kernel.m_id_readr.begin())
{
//读卡器已连接
_kernel.m_drive.idreadr = true;
ui::bitmap(hDC, hc, 695, 25);
}
}
if (_kernel.m_drive.camera == false)
{
if (_kernel.m_face.begin(_kernel.m_mainwnd))
{
//摄像头已连接
_kernel.m_drive.camera = true;
ui::gif(GetDesktopWindow(), IDR_LOADING, false);
ui::bitmap(hDC, hb, 645, 25);
ShowWindow(_kernel.m_mainwnd, SW_SHOW);
}
else
{
_kernel.m_drive.camera = true;
ui::gif(GetDesktopWindow(), IDR_LOADING, false);
MessageBox(_kernel.m_mainwnd, "请插入授权USB锁,重启程序", "信息", MB_OK);
ShowWindow(_kernel.m_mainwnd, SW_SHOW);
}
}
if (_kernel.m_drive.network == false)
{
//网络已连接
if (_kernel.m_network.begin())
{
_kernel.m_drive.network = true;
ui::bitmap(hDC, ha, 596, 25);
}
}
if (_kernel.m_drive.gate == false)
{
if (_kernel.m_com.open(atoi(_kernel.m_config.com), 9600, 8, NULL))
{
//闸机器已连接
_kernel.m_drive.gate = true;
ui::bitmap(hDC, hd, 746, 25);
}
}
::DeleteObject(hd);
::DeleteObject(hc);
::DeleteObject(hb);
::DeleteObject(ha);
::ReleaseDC(_kernel.m_mainwnd, hDC);
}
请问这种情况怎么处理比较好?
您好,我是有问必答小助手,您的问题已经有小伙伴解答了,您看下是否解决,可以追评进行沟通哦~
如果有您比较满意的答案 / 帮您提供解决思路的答案,可以点击【采纳】按钮,给回答的小伙伴一些鼓励哦~~
ps:问答VIP仅需29元,即可享受5次/月 有问必答服务,了解详情>>>https://vip.csdn.net/askvip?utm_source=1146287632