月度归档:2005年08月

我快六个月啦

我的本事越来越大了。今天喝了点水,爸爸就把奶瓶放下了。我觉得不过瘾,两只手自己抱着前面的奶瓶就往嘴里送,就是不知道怎么举起来,怎么也喝不着东西
还有,我看到《杜拉克管理思想全书》那本书,封面是个老头,一脸严肃,我想是杜拉克吧,我挺喜欢这个老头,爸爸把这本书一放在我面前,我就笑了
?

宝宝哭闹可能的情况

老婆怕我不会看孩子,专门给我写的:
1. 渴了,给点水喝(如拉肚子,可加点蒙脱石)
2. 饿了,给点奶粉,温了再喝
3. 热了,闷了,可抱到凉爽的地方透透气
4. 想尿了或拉了,一般不会太闹,把不出来就顺其自然好了,可以给穿纸尿裤,别卡着肉
5. 想睡了,给点奶或水喝,就慢慢睡了
6. 想要什么东西,如果是不该给的,可以用和她玩玩别的东西代替
7. 不想躺了,或者坐了,那就让她站着玩,或者抱她转转,看看她喜欢看的灯光,还有音乐,空气

MFC 线程的一个问题

我们公司的服务器程序一直运行得很好,但在用户一台特别高配置(2G内存,8CPU)的机器上出问题了。根据Drwtsn32的输出,查出来问题出在MFC中thrdcore.cpp中第59行

44:UINT APIENTRY _AfxThreadEntry(void* pParam)
45:{
46:??? _AFX_THREAD_STARTUP* pStartup = (_AFX_THREAD_STARTUP*)pParam;

58:??? ??? _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
59:??? ??? pThreadState->m_pModuleState = pStartup->pThreadState->m_pModuleState;

出错时,pStartup->pThreadState 已经是非法值了,而pStartup是作为线程处理函数的参数传入并赋值的。

再看调用_AfxThreadEntry的地方:

385: BOOL CWinThread::CreateThread(DWORD dwCreateFlags, UINT nStackSize,
386:??? LPSECURITY_ATTRIBUTES lpSecurityAttrs)
387:{

398:??? _AFX_THREAD_STARTUP startup; memset(&startup, 0, sizeof(startup));
399:??? startup.pThreadState = AfxGetThreadState();

414:??? // create the thread (it may or may not start to run)
415:??? m_hThread = (HANDLE)_beginthreadex(lpSecurityAttrs, nStackSize,
416:??? ??? &_AfxThreadEntry, &startup, dwCreateFlags | CREATE_SUSPENDED, (UINT*)&m_nThreadID);

问题就可能出在startup是个局部变量,当_AfxThreadEntry尚未执行完毕时,有可能CWinThread::CreateThread()很快完成退出,导致startup内容被更改。特别是在多CPU的机器上,可能性更大?

不用MFC的线程,直接用C库函数_beginthread,解决此问题。折腾了好几天。