Why does calling GetDlgItem cause an access violation?

1

I am trying to access one of my MFC view's dialog elements. To do this, I run the following line of code:

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

This causes the following exception:

Exception thrown at 0x53072844 (mfc140ud.dll) in NameOfMyApplication.exe: 0xC0000005: Access violation reading location 0x00000020.

What's strange about this is that the line above it does not cause an access violation, despite being basically the same thing. The line above it is:

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

Does anyone know why this is happening?

mfc
asked on Stack Overflow Jun 7, 2017 by JTM • edited Jun 7, 2017 by JTM

2 Answers

3

Obviously, the item with the ID IDC_RADIO_VIEW1 exists, but the item with the ID IDC_RADIO_VIEW2 does not exist. So when you try to retrieve that dialog item, you get a NULL pointer. Yet you cast it to a CButton pointer and then attempt to dereference it without validating the pointer. Right there, you've invoked undefined behavior. Your program has a serious bug, and anything could happen. Luckily, the runtime environment jumped in and issued an access violation before the nasal demons could be unleashed.

The correct way to write the code would be to validate functions' return values. If nothing else, use an assertion:

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

This would have given you a very readable (and debuggable) error message.

Note that it would also be more readable to use symbolic constants, rather than magic numbers. So you should be writing SetCheck(BST_UNCHECKED) (or BST CHECKED or BST_INDETERMINATE).

answered on Stack Overflow Jun 7, 2017 by Cody Gray
0

There is no control with ID IDC_RADIO_VIEW2 as an immediate child of the dialog where you are calling the code.

The line of code that doesn't fail references a control with ID IDC_RADIO_VIEW1. It stands to reason, that the dialog has an immediate child window with ID IDC_RADIO_VIEW1.

I'm sure, that calling ((CButton*)GetDlgItem( IDC_RADIO_VIEW999 ))->SetCheck( 1 ); will exhibit a totally different error, although being "basically the same thing". You really need to learn, how computers work. Code doesn't work because it is similar to other working code (for some definition of "similar").

answered on Stack Overflow Jun 7, 2017 by IInspectable • edited Jun 7, 2017 by IInspectable

User contributions licensed under CC BY-SA 3.0