下面的程序你能看出来哪里有问题吗?
void MyFun() { WCHAR wszFileName[MAX_PATH] = L"C://test.txt"; _beginthread(ThreadFun, 0, wszFileName); } void ThreadFun(void *pArguments) { //do something //... WCHAR wszFileName[MAX_PATH] = L""; wcscpy_s(wszFileName, MAX_PATH, (WCHAR *)pArguments); TRACE(L"input file name: %s/n", wszFileName); //deal with C:/test.txt //... _endthread(); }
在某些情况下,TRACE出来的语句可能没有文件名。
原因很简单,有些人可能已经看出来了。这个问题也是我刚开始做多线程开发时常遇到的问题。
由于MyFun中的wszFileName字符串为临时变量,因此该字符串在MyFun返回后即被释放。所以,对于线程函数中的语句 wcscpy_s(wszFileName, MAX_PATH, (WCHAR *)pArguments); , 在执行这句之前,MyFun函数可能已经返回,此时pArguments所指向的内存已经无效,也就得不到文件名了。
这个错误是由于多线程的特性导致的,在单线程中,MyFun一定是在ThreadFun返回才返回的,所以就没有这个问题,而初学多线程的人忘记考虑了这点,因此可能会犯错。
修改方法非常简单,将MyFun中的wszFileName声明为全局变量即可,但这样会导致全局变量滥用,不推荐。另一种更为推荐的方法是将wszFileName声明为Static类型,如下:
static WCHAR wszFileName[MAX_PATH] = L"C://test.txt";
这样即保证了变量的局部性,也不会在函数退出后释放该变量。