I create, use, and delete an array of CDBVariant :
CDBVariant *myVars = new CDBVariant[N];
// ...
delete[] myVars;
On the delete[] line the execution meets 3 breakpoints I can't explore, then Access Violations in reading over and over until it crashes. I have the exact same symptoms as this guy : http://computer-programming-forum.com/82-mfc/549a933737d9177d.htm ; namely I can use new[]/delete[] on other object types with no problem, and I can wrap the CDBVariant in a useless class and create/delete arrays of this class.
This happens specifically while using MFC. If I create a new console app and launch this;
#include <cassert>
#include <afxdb.h>
int main(void)
{
CDBVariant *vars = new CDBVariant[10];
assert(vars[0].m_dwType == DBVT_NULL); // don't optimise my array away please.
delete[] vars;
}
it wont cause any trouble. If, however, I create a basic, default MFC app (dialog-based, 'cause that's what I use) and use the OK button of the default dialog to do the same thing;
void CMFCApplication1Dlg::OnBnClickedOk()
{
CDBVariant *vars = new CDBVariant[10];
assert(vars[0].m_dwType == DBVT_NULL);
delete[] vars;
CDialogEx::OnOK();
}
once again, breaks, then access violations, then death. (I use VS2017 with MSVC 19.10.25027.)
Please tell me what causes this, and how to properly avoid it.
Here are the requested disassembly codes. Sorry for the heaviness. Here is the console version:
delete[] vars;
00558E6D mov eax,dword ptr [vars]
00558E70 mov dword ptr [ebp-110h],eax
00558E76 mov ecx,dword ptr [ebp-110h]
00558E7C mov dword ptr [ebp-104h],ecx
00558E82 mov edx,dword ptr [ebp-104h]
00558E88 mov dword ptr [ebp-0F8h],edx
00558E8E cmp dword ptr [ebp-0F8h],0
00558E95 je main+172h (0558EF2h)
00558E97 mov eax,dword ptr [ebp-0F8h]
00558E9D cmp dword ptr [eax-4],0
00558EA1 je main+148h (0558EC8h)
00558EA3 mov esi,esp
00558EA5 push 3
00558EA7 mov ecx,dword ptr [ebp-104h]
00558EAD mov edx,dword ptr [ecx]
00558EAF mov ecx,dword ptr [ebp-104h]
delete[] vars;
00558EB5 mov eax,dword ptr [edx]
00558EB7 call eax
00558EB9 cmp esi,esp
00558EBB call __RTC_CheckEsp (0515C33h)
00558EC0 mov dword ptr [ebp-118h],eax
00558EC6 jmp main+164h (0558EE4h)
00558EC8 mov ecx,dword ptr [ebp-0F8h]
00558ECE sub ecx,4
00558ED1 push ecx
00558ED2 call operator delete[] (052763Bh)
00558ED7 add esp,4
00558EDA mov dword ptr [ebp-118h],0
00558EE4 mov edx,dword ptr [ebp-118h]
00558EEA mov dword ptr [ebp-11Ch],edx
00558EF0 jmp main+17Ch (0558EFCh)
00558EF2 mov dword ptr [ebp-11Ch],0
The call eax line leads to
CDBVariant::`vector deleting destructor':
0051EC84 jmp CDBVariant::`vector deleting destructor' (0556E30h)
which immediately jumps away to a big block of code, introduced as CDBVariant::`vector deleting destructor'.
The MFC version looks very similar at first:
delete[] vars;
00FB7D0A mov eax,dword ptr [vars]
00FB7D0D mov dword ptr [ebp-11Ch],eax
00FB7D13 mov ecx,dword ptr [ebp-11Ch]
00FB7D19 mov dword ptr [ebp-110h],ecx
00FB7D1F mov edx,dword ptr [ebp-110h]
00FB7D25 mov dword ptr [ebp-104h],edx
00FB7D2B cmp dword ptr [ebp-104h],0
00FB7D32 je CMFCApplication1Dlg::OnBnClickedOk+18Fh (0FB7D8Fh)
00FB7D34 mov eax,dword ptr [ebp-104h]
00FB7D3A cmp dword ptr [eax-4],0
00FB7D3E je CMFCApplication1Dlg::OnBnClickedOk+165h (0FB7D65h)
00FB7D40 mov esi,esp
00FB7D42 push 3
00FB7D44 mov ecx,dword ptr [ebp-110h]
00FB7D4A mov edx,dword ptr [ecx]
00FB7D4C mov ecx,dword ptr [ebp-110h]
00FB7D52 mov eax,dword ptr [edx]
00FB7D54 call eax
00FB7D56 cmp esi,esp
00FB7D58 call __RTC_CheckEsp (0FB1474h)
00FB7D5D mov dword ptr [ebp-124h],eax
00FB7D63 jmp CMFCApplication1Dlg::OnBnClickedOk+181h (0FB7D81h)
00FB7D65 mov ecx,dword ptr [ebp-104h]
00FB7D6B sub ecx,4
00FB7D6E push ecx
00FB7D6F call operator delete[] (0FB1B4Fh)
00FB7D74 add esp,4
00FB7D77 mov dword ptr [ebp-124h],0
00FB7D81 mov edx,dword ptr [ebp-124h]
00FB7D87 mov dword ptr [ebp-128h],edx
00FB7D8D jmp CMFCApplication1Dlg::OnBnClickedOk+199h (0FB7D99h)
00FB7D8F mov dword ptr [ebp-128h],0
but its call eax goes here:
0FCF7810 push ebp
0FCF7811 mov ebp,esp
0FCF7813 push ecx
0FCF7814 mov dword ptr [ebp-4],0CCCCCCCCh
0FCF781B mov dword ptr [ebp-4],ecx
0FCF781E mov ecx,dword ptr [ebp-4]
0FCF7821 call 0FCF77B0
0FCF7826 mov eax,dword ptr [ebp+8]
0FCF7829 and eax,1
0FCF782C je 0FCF783C
0FCF782E push 18h
0FCF7830 mov ecx,dword ptr [ebp-4]
0FCF7833 push ecx
0FCF7834 call 0FE87AB0
0FCF7839 add esp,8
0FCF783C mov eax,dword ptr [ebp-4]
0FCF783F add esp,4
0FCF7842 cmp ebp,esp
0FCF7844 call 0FE879E0
0FCF7849 mov esp,ebp
0FCF784B pop ebp
0FCF784C ret 4
The first break happens here:
ntdll.dll!770e48c2() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!770843d7() Unknown
KernelBase.dll!73bf4814() Unknown
ucrtbased.dll!0fdf611b() Unknown
ucrtbased.dll!0fdf4a0e() Unknown
ucrtbased.dll!0fdf75bc() Unknown
mfc140ud.dll!0f641372() Unknown
mfc140ud.dll!0fa97abc() Unknown
mfc140ud.dll!0f907839() Unknown
MFCApplication1.exe!CMFCApplication1Dlg::OnBnClickedOk() Line 96 C++
the second and third a bit higher:
ucrtbased.dll!0fdf4a3a() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ucrtbased.dll]
ucrtbased.dll!0fdf75bc() Unknown
mfc140ud.dll!0f641372() Unknown
mfc140ud.dll!0fa97abc() Unknown
mfc140ud.dll!0f907839() Unknown
MFCApplication1.exe!CMFCApplication1Dlg::OnBnClickedOk() Line 96 C++
and finally the call stack gets lost and the execution loops sending exceptions from there:
ucrtbased.dll!0fe55f0c() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ucrtbased.dll]
ucrtbased.dll!0fe563d1() Unknown
ucrtbased.dll!0fe55dcb() Unknown
ucrtbased.dll!0fe56d02() Unknown
ucrtbased.dll!0fe468a9() Unknown
ucrtbased.dll!0fe464bf() Unknown
ucrtbased.dll!0fe3d8a2() Unknown
ucrtbased.dll!0fe37319() Unknown
ucrtbased.dll!0fe2f545() Unknown
ucrtbased.dll!0fdface6() Unknown
ucrtbased.dll!0fdfa17b() Unknown
ucrtbased.dll!0fdf8043() Unknown
"0xC0000005: Access violation reading location 0x00000047."