老生常谈,C语言变量生存周期

2017-01-11  本文已影响0人  止愚至善
假设创建线程的接口如下
/*
@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就是正确的了。

上一篇下一篇

猜你喜欢

热点阅读