【MFC】CCriticalSection类在Release编译下调用Lock函数会报错0xC0000008
问题描述
通过以下伪代码方式描述问题:
主对话框类内创建成员变量及结构体变量:
typedef struct MSG_INFO
{
int a;
int b;
char c[10];
}MSGINFO;
MSG_INFO m_mi;
CCriticalSection m_cs;
CMyDll m_dll;
在DLL内有一成员变量 :
class MYDLL CMyDll
{
CCriticalSection *m_pcs;
MSG_INFO *m_pmi;
}
现需要实现在DLL工程内能够对主线程内的m_mi进行赋值操作,同时为避免两边现成同时对m_mi进行操作,所以通过以下方式实现关联:
m_dll.m_pcs = &m_cs;
m_dll.m_pmi= &m_mi;
此方法在Debug下调试是可行的,但是在Release下一旦DLL内程序执行到如下代码语句时就会报错:
//DLL内处理代码
m_pcs->Lock();
//功能执行
。。。
m_pcs.Unlock();
后定位到错位位置为Lock()函数内调用API函数::EnterCriticalSection(&m_sect)时便会报错:
通过分析,个人认为导致此错误的直接原因是m_sect的值是异常导致的(未必正确)
但是后面场后过指针,或者对m_sect进行初始化,都无法解决该问题。
在无法发现根本原因,所以只能再次提供两个方法来处理此问题:
方法一 CRITICAL_SECTION代替CCriticalSection
直接声明CRITICAL_SECTION结构体来代替CCriticalSection。
CRITICAL_SECTION m_cs;
InitializeCriticalSection(&m_cs);
然后还是通过问题描述的方式传递给DLL内成员变量,处理函数修改为:
EnterCriticalSection(m_pcs);
//功能执行
。。。
LeaveCriticalSection(m_pcs);
方法二 使用WaitForSingleObject和ReleaseMutex()
主对话框内定义成员变量并对其进行初始化:
HANDLE m_hMutex;
m_hMutex = CreateMutex(NULL,FALSE,NULL); //第二个参数为FALSEE,互斥对象的所有权为空,处于空闲状态
//第二个参数为TRUE,互斥对象的所有权为主线程所有,非空闲状态
//DLL传递参数
m_dll.m_hMutex = m_hMutex;
DLL内处理函数修改为:
WaitForSingleObject(m_hMutex , INFINITE);//第二个参数为INFINITE表示一直等待,直到拥有互斥对象
//功能执行
。。。
::ReleaseMutex(m_hMutex);//使用完毕,将互斥对象还给操作系统
说明:
在调用CreateMutex()创建互斥对象时:
若对象所有权为空,则主线程和子线程中分别等待互斥量,即主线程和子线程交替输出;
若标志位TRUE,则互斥对象所有权对创建的线程调用,其余线程无法调用此互斥对象。
此处引用网上的说法:
如创建进程希望立即拥有互斥体,则设为TRUE。一个互斥体同时只能由一个线程拥有。是FALSE,表示刚刚创建的这个Mutex不属于任何线程 也就是没有任何线程拥有他,一个Mutex在没有任何线程拥有他的时候,他是处于激发态的, 所以处于有信号状态。
结语
导致问题出现的根本原因尚未找到,只是在此处提出两个方案来解决此问题,若各位有其他的建议和看法,欢迎来评论区讨论。