【问题标题】:Why does calling GetDlgItem cause an access violation?为什么调用 GetDlgItem 会导致访问冲突?
【发布时间】:2017-06-07 14:40:04
【问题描述】:

我正在尝试访问我的 MFC 视图的对话框元素之一。为此,我运行以下代码行:

    ((CButton*)GetDlgItem( IDC_RADIO_VIEW2 ))->SetCheck( 0 );

这会导致以下异常:

在 NameOfMyApplication.exe 中的 0x53072844 (mfc140ud.dll) 处引发异常:0xC0000005:访问冲突读取位置 0x00000020。

奇怪的是,它上面的行并没有导致访问冲突,尽管它们基本上是一样的。上面一行是:

    ((CButton*)GetDlgItem( IDC_RADIO_VIEW1 ))->SetCheck( 1 );

有人知道为什么会这样吗?

【问题讨论】:

    标签: mfc


    【解决方案1】:

    很明显,ID为IDC_RADIO_VIEW1的项目存在,但ID为IDC_RADIO_VIEW2的项目不存在。因此,当您尝试检索该对话框项时,您会得到一个 NULL 指针。然而,您将它转换为 CButton 指针,然后尝试取消引用它而不验证指针。就在那里,您调用了未定义的行为。你的程序有一个严重的错误,任何事情都可能发生。幸运的是,运行时环境在nasal demons 被释放之前就介入并发出了访问冲突。

    编写代码的正确方法是验证函数的返回值。如果不出意外,请使用断言:

    CButton* pBtn = ((CButton*)GetDlgItem(IDC_RADIO_VIEW2));
    ASSERT(pBtn != NULL);
    pBtn->SetCheck(0);
    

    这会给您一个非常易读(且可调试)的错误消息。

    请注意,使用符号常量而不是幻数也更具可读性。所以你应该写SetCheck(BST_UNCHECKED)(或BST CHECKEDBST_INDETERMINATE)。

    【讨论】:

    • 那个“鼻恶魔”的东西很搞笑。感谢分享!
    【解决方案2】:

    没有 ID IDC_RADIO_VIEW2 的控件作为您调用代码的对话框的直接子级。

    没有失败的代码行引用了 ID 为 IDC_RADIO_VIEW1 的控件。按理说,该对话框有一个 ID 为 IDC_RADIO_VIEW1 的直接子窗口。

    我敢肯定,调用((CButton*)GetDlgItem( IDC_RADIO_VIEW999 ))->SetCheck( 1 ); 会出现完全不同的错误,尽管是“基本上是同一件事”。你真的需要学习,计算机是如何工作的。代码不起作用,因为它与其他工作代码相似(对于 “相似” 的某些定义)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-29
      • 1970-01-01
      • 2012-01-30
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多