【发布时间】:2021-05-18 16:58:21
【问题描述】:
问题:在 MFC 应用程序的某些部分代码中,主应用程序 (theApp) 的某些成员变量未在正确位置访问。 伪代码: 主应用有很多成员类
类 CMarcaApp : public CWinAppEx{ …… 公开:
CMyClass1 m_class1; CMyClass2 m_class2; ... ... 步骤重复 m_stepprepeat; ....
StepRepeat 是一个带有一些变量的简单类。
此应用程序中还存在许多对话框类。其中一些是根据鼠标事件打开的,例如在大型机类中。
Mainframe::Onclicked(){
CMyDialog dlg;
dlg.DoModal();
}
问题是,打开某个对话框(与任何其他对话框没有太大区别),并访问“theApp”的成员变量(通过 AfxGetApp() 或 theApp 作为外部全局变量),内容此类成员的变量不再正确。我发现指向此类变量的“指针”不再正确。换句话说:
&(theApp->m_steprepeat) is no longer pointing to the correct place.
这绝对是烦人的。我可以在反汇编代码中看到,通过在尝试访问 m_class2 时向 (theApp) 的指针添加错误的偏移量,反汇编代码完全是错误的。
我在Debug窗口看到m_class2的成员没有任何意义,所以我创建了一个全局变量StepRepeat *theSteprepeat;
在 Initinstance() 中,这个指针被初始化为 theSteprepeat= &(theApp->m_stepprepeat)
我可以从任何地方访问“theSteprepeat”及其成员变量,一切看起来都很好,但在某些范围内(例如,在某些 OnInitDialog() 函数内),方向 &(theApp->m_steprepat) 与“theSteprepeat”不匹配。
在反汇编代码中,我可以看到“偏移量”确实是错误的,这取决于我访问此变量的“位置”。 在这里,您可以看到“相同 C++”代码的反汇编代码以及两种情况下的不同之处。
正确的反汇编代码:在应用程序的某个地方调用
5460: StepRepeat *ps = &(app->m_steprepeat);
008A7FE0 8B 45 E0 mov eax,dword ptr [app]
008A7FE3 05 CC 43 02 00 add eax,243CCh
008A7FE8 89 45 BC mov dword ptr [ps],eax
错误的反汇编代码:在应用内的其他地方调用
67: StepRepeat *ps = &(app->m_steprepeat);
00AFB836 8B 45 E0 mov eax,dword ptr [app]
00AFB839 05 3C 43 02 00 add eax,2433Ch
00AFB83E 89 45 BC mov dword ptr [ps],eax
如您所见,两个反汇编代码中的偏移量是不同的。第一个代码中的 243CCh,第二个代码情况下的 2433Ch。 'app' 是指向 'theApp' 或 AfxGetApp() 的本地指针(在这两种情况下都会发生同样的事情)。代码 StepRepeat *ps = &(app->m_stepprepeat) 是为了调试而添加的,因为我很想知道会发生什么。
此问题不仅限于“StepRepeat”成员,还适用于“CMyClass2 或其他一些成员)。CMarcaApp 类有很多成员,而且这个问题似乎只发生在声明为靠近类定义的结尾。如果我将它们移到开头,则不会发生问题,尽管我认为问题只是转移到了其他一些成员(我没有检查)。
有什么提示吗?
【问题讨论】:
-
这看起来像是您对
app类有多个定义(大小不同),或者您对类进行了更改,但使用它的所有内容都没有重新编译。 -
大小不匹配的第二个选项是混合调试和发布。意味着将调试库链接到发布应用程序或 viseversa
-
听起来你的架构有点不对劲。你能画出你的类以及它们如何相互作用吗?例如。在您的 OnClicked 方法中,“正常”方式是将
this指针传递给对话框 CMyDialog dlg(this),这样当用户在对话框中按下 OK 而不是通过某个全局变量时,就可以设置任何值 -
当您在类层次结构中使用 C 风格的强制转换时,可能会发生这种情况。编译器信任您,并根据提供的类型信息计算偏移量。如果该类型信息不正确,则偏移量开始看起来错误。
-
这样做。在此过程中的每一步,记录/打印类外的
sizeof(app)的值以及类方法内的sizeof(*this)的值。某处会出现大小之间的不匹配。当您在 .h 和 .cpp 文件之间定义不同的预处理器时,就会发生这种情况。当您添加\删除成员变量但忘记“构建干净”(重新编译并重新链接所有内容)时,也会发生这种情况。当你错误地施法时也会发生这种情况。
标签: c++ visual-studio-2015 mfc