假设创建线程的接口如下
/*
@param[in]:
char *pThreadName 线程名称
int nPriority 优先级
int nStackSize 线程栈空间
ThreadEntry fnThreadEntry 线程入口函数(函数指针)
void *pAry 入口函数的参数
@param[out]:
ThreadHandle 线程句柄
*/
ThreadHandle threadCreate(char *pThreadName, int nPriority, int nStackSize, ThreadEntry fnThreadEntry, void *pAry);
创建线程调用的过程可能如下:
int init(void)
{
HANDLE handle = creatHandle();//某个会生成句柄的函数
ThreadHandle threadHandle = threadCreate("myThreadName", 10, 10*1024, fnProcess, (void*)&handle);//创建线程,handle 句柄线程作为入口函数的参数
// do something
}
void fnProcess(void *pAry)
{
if(!pAry)
{
return;
}
HANDLE hCurHandle= * (HANDLE *)pAry;
//do something
}
发现创建线程时,传入的参数(void)&handle
,与入口函数接收到的参数pAry
是匹配的;但是强制转换后HANDLE hCurHandle= * (HANDLE *)pAry;
得到的hCurHandle
不等于传入的handle
。
强制转换的前后地址都是对的,但是取值的结果不一样,遇到这个问题,刚开始以为是强制转换导致的,后面才往变量声明周期上考虑,HANDLE handle
是一个栈变量,当函数 int init(void)
执行完毕,该变量的内存空间会被销毁,因此创建线程时传入的(void*)&handle
其实是一个野指针,导致void fnProcess(void *pAry)
中得到的地址貌似是对的,实则地址上的内容不合法,也就是获取到不确定的错误句柄hCurHandle
。
这个问题比较隐蔽,实则是老生常谈的变量生命周期的问题。
可以这样处理,创建线程时直接将 handle
强转为 (void *)handle
传入,线程处理函数接收到参数后直接强转为HANDLE hCurHandle= (HANDLE)pAry
,这样得到的handle
就是正确的了。
网友评论