100分 诚征解答 问题复杂 诚请高手答复

zf0579 2004-04-26 11:02:10
问题见后:
1) THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)
#define THREAD_LOCAL(class_name, ident_name) \
AFX_DATADEF CThreadLocal<class_name> ident_name;

2)
template<class TYPE>
class CThreadLocal : public CThreadLocalObject
{
// Attributes
public:
AFX_INLINE TYPE* GetData()
{
TYPE* pData = (TYPE*)CThreadLocalObject::GetData(&CreateObject);
ASSERT(pData != NULL);
return pData;
}
AFX_INLINE TYPE* GetDataNA()
{
TYPE* pData = (TYPE*)CThreadLocalObject::GetDataNA();
return pData;
}
AFX_INLINE operator TYPE*()
{ return GetData(); }
AFX_INLINE TYPE* operator->()
{ return GetData(); }

// Implementation
public:
static CNoTrackObject* AFXAPI CreateObject()
{ return new TYPE; }
};

问题:
_AFX_THREAD_STATE* pState = _afxThreadState;
此语句中,_afxThreadState的类型是CThreadLocal<_AFX_THREAD_STATE>, pState的类型是_AFX_THREAD_STATE*,将_afxThreadState赋值给pState。不同类型之间赋值显然会出现编译错误,但是MFC就是这么做的。
在这赋值语句中,_afxThreadState会调用到CThreadLocal<_AFX_THREAD_STATE>的operator->()得到_AFX_THREAD_STATE类型数据返回给给pState。但是_afxThreadState并没有显示调用operator->()。
现在想不明白_afxThreadState怎么会调用到perator->呢?请高手指点。
100分送上
...全文
84 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
zf0579 2004-04-29
  • 打赏
  • 举报
回复
我觉得解释成Bug总是不妥, MFC版本都到4.2啦 难道微软的人还会保留这个Bug?
zf0579 2004-04-27
  • 打赏
  • 举报
回复
?_afxThreadState@@3V?$CThreadLocal@V_AFX_THREAD_STATE@@@@A:
5F4CE13C 01 00 add dword ptr [eax],eax
5F4CE13E 00 00 add byte ptr [eax],al

可能确实不匹配, 那它是怎么实现这项技术的呢? 怎么能定位到这里的?

89: THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)
5F48FC11 55 push ebp
5F48FC12 8B EC mov ebp,esp
5F48FC14 5D pop ebp
5F48FC15 C3 ret

这个宏也能生成代码?一般情况下,宏难以生成代码的,所以也调试不到。
zf0579 2004-04-27
  • 打赏
  • 举报
回复
235: _AFX_THREAD_STATE* pState = _afxThreadState;
5F49025A B9 3C E1 4C 5F mov ecx,offset _afxThreadState (5f4ce13c)
5F49025F E8 DC EC FF FF call CThreadLocal<_AFX_THREAD_STATE>::operator-> (5f48ef40)
5F490264 89 45 FC mov dword ptr [pState],eax

我把其汇编代码拷贝下来啦,可以看到确实调用啦CThreadLocal<_AFX_THREAD_STATE>::operator->
freefalcon 2004-04-27
  • 打赏
  • 举报
回复
555,帖子沉下去了,好不容易找出来,问题都解决了
每有必要再深究了吧,即使是bug,二者的返回值都是一样的,也不会造成漏洞
zf0579 2004-04-27
  • 打赏
  • 举报
回复
做过验证啦, 果然不同, 为什么呢?
zf0579 2004-04-27
  • 打赏
  • 举报
回复
实在有意思!难道是Bug, 这个版本都到4.2啦,难道微软开发人员如此粗心?!
或者,微软是基于什么考虑,让静态连接库与动态链接库,在相同的语句上调用不同的函数呢?

非常佩服你(oyd)在此程序方面的功力,谢谢!
五一前,我把此贴结啦。你80,freefalcon20。
在你说的情况下(静态链接),他的解释也是正确的。
oyd 2004-04-27
  • 打赏
  • 举报
回复
如果仍然不信是微软的bug,那么你把工程设置改为使用静态库连接MFC,再按照你的方法一步一步F11,你会发现这一次调用的就是operator thread_state*()了
oyd 2004-04-27
  • 打赏
  • 举报
回复
我想我已经找到答案了
如下://lib.cpp
template<class T>
class abc
{
public:
T* operator ->(){return m_p;}
operator T*(){return m_p;}
T* m_p;
};
abc<_AFX_THREAD_STATE> _afxchar;
void function()
{
_AFX_THREAD_STATE* pState = _afxstate.operator ->();
}
// main.cpp
extern void function();
int main()
{
function();
return 0;
}
以上main.cpp编译成exe,lib.cpp编译成static lib
link之后,再把lib.cpp中的
_AFX_THREAD_STATE* pState = _afxstate.operator ->();
改成
_AFX_THREAD_STATE* pState = _afxstate
不重新编译。
这时调试时的现象便和楼主所说的如出一辙了,虽然微软不太可能这么愚弄我们,但是实在找不到其他可能性了。
hab1980 2004-04-27
  • 打赏
  • 举报
回复
微软的MFC,隐藏了太多关键性代码,想吃透它?<嘿嘿...> 准备掉几斤肉吧!
hafeng 2004-04-26
  • 打赏
  • 举报
回复
关注
oyd 2004-04-26
  • 打赏
  • 举报
回复
对于这个问题,我想答案应该要找微软了
因为在我做的实验中,如果自己按照MFC库同样的声明一个模版类(一切同上,仅改名)
声明一个THREAD_LOCAL(_AFX_THREAD_STATE, _afxThreadState)

然后f11进去看,的确调用的是AFX_INLINE operator TYPE*()

因为MFC的库不是我们编译的,我们只使用了头文件,所以我们不敢保证微软提供的lib和.h一定匹配。
而且关键在于TYPE*()和->()的实现完全一样,所以根本就不能用其他方法发现微软到底定义的是什么样类型的_afxThreadState。


freefalcon 2004-04-26
  • 打赏
  • 举报
回复
果然如此!

等等,再想一想.....
zf0579 2004-04-26
  • 打赏
  • 举报
回复
Faint, 我当然是在_AFX_THREAD_STATE* pState = _afxThreadState;上加断点,然后按F11啦。麻烦你们做个实验,就知道我说的是真的。虽然我很愿意相信freefalcon的,但是实际情况不是这样的。

用MFC生成一个程序,然后在CTestApp::CTestApp{ 括号这里加个断点,然后不断按F11, 你一定会看到_AFX_THREAD_STATE* pState = _afxThreadState; 然后按F11
会调用->,可以实验一下。

对这个语法现象,我想了好几天,一直不能理解 :(
oyd 2004-04-26
  • 打赏
  • 举报
回复
没有停在TYPE*()的GetData(); 这一定是你自己的错
据我分析,一定还没到达你这条语句,_AFX_THREAD_STATE* pState = _afxThreadState;

你先去除所有断点,再在_AFX_THREAD_STATE* pState = _afxThreadState;上加断点,然后按F5再按F11你就明白了。
zf0579 2004-04-26
  • 打赏
  • 举报
回复
你的想法,我在MFC上验证过啦。同时在这两个函数打上断点(AFXTLS_.h)。
AFX_INLINE operator TYPE*()
{ return GetData(); }
AFX_INLINE TYPE* operator->()
{ return GetData(); }
结果断点停在AFX_INLINE TYPE* operator->()的GetData()上。
是不是这样的,首先调用TYPE*()然后又调用operator->()啦?那为何不停在TYPE*()?
总之,没有停在TYPE*()的GetData();
freefalcon 2004-04-26
  • 打赏
  • 举报
回复
实际上就是
void main()
{
thread_local<thread_state> _afx_threadstate;
thread_state* state_ptr = (thread_state*)_afx_threadstate; //这里调用thread_local<thread_state>的operator thread_state*()
}
ejiue 2004-04-26
  • 打赏
  • 举报
回复
To楼上:

thread_local<thread_state> _afx_threadstate;
thread_state* state_ptr = _afx_threadstate;
这两句怎解?
freefalcon 2004-04-26
  • 打赏
  • 举报
回复
楼主看见这句了吗
AFX_INLINE operator TYPE*()
这便是用于转化的,而不是你所认为的operator->

下面模拟了一段代码

template<class T>
class thread_local
{
public:
operator T*()
{
return obj;
}
private:
T* obj;
};

class thread_state
{
public:
thread_state(){
}
};

void main()
{
thread_local<thread_state> _afx_threadstate;
thread_state* state_ptr = _afx_threadstate;
}

64,661

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧