Trouble with double variable ddx_text on VC2015.

Asked 2 years ago, Updated 2 years ago, 108 views

I am creating a win32 dialog-based app in the Visual Studio 2015 Community Edition MFC, and I am having trouble with the mysterious behavior of ddx_text in the release version.It looks normal in the Debug version.
The following is an application with three edit boxes and an update button that displays double variables as bugcheck.exe to explain the behavior.

Immediately after starting the app, the edit box displays the initial values of the double variables f1, f2, f3 (where f3 is 0).
If you type 0 in the f2 edit box, the display is 0.
However, if you press the button and updateData(false) the dialog, the f2 and f3 display values will be 5.(There are some variations depending on the location and number)
I thought that if I put 0 in the third parameter such as DDX_Text(pDX, IDC_EDIT1, m_f1), the result might be strange, but I can't help but use 0 so I'm in trouble.

Below is the code equivalent to the difference from the auto-generated portion of the bugcheck.

--bugcheckDlg.h --

class CbugcheckDlg:public CDialogEx
{
approximately
public:
double m_f1;
double m_f2;
double m_f3;// Read only
afx_msg void OnBnClickedButton1(); // Update controls
afx_msg void OnEnChangeEdit1();
afx_msg void OnEnChangeEdit2();

}

--bugcheckDlg.cpp --

CbugcheckDlg::CbugcheckDlg(CWnd*pParent/*=NULL*/)
: CDialogEx (IDD_BUGCHECK_DIALOG, pParent)
, m_f1 (1.5)
, m_f2(0.1)
, m_f3(0.0)
{
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CbugcheckDlg::DoDataExchange (CDataExchange*pDX)
{
CDialogEx::DoDataExchange (pDX);
DDX_Text(pDX,IDC_EDIT1,m_f1);
DDX_Text(pDX, IDC_EDIT2, m_f2);
DDX_Text(pDX, IDC_EDIT3, m_f3);
}

BEGIN_MESSAGE_MAP (CbugcheckDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED (IDC_BUTTON1, & CbugcheckDlg::OnBnClickedButton1)
ON_EN_CHANGE (IDC_EDIT1, & CbugcheckDlg::OnEnChangeEdit1)
ON_EN_CHANGE (IDC_EDIT2, & CbugcheckDlg::OnEnChangeEdit2)
END_MESSAGE_MAP()

void CbugcheckDlg::OnBnClickedButton1()
{
UpdateData(false);
}

void CbugcheckDlg::OnEnChangeEdit1()
{
UpdateData(true);
}

void CbugcheckDlg::OnEnChangeEdit2()
{
UpdateData(true);
}

--resource.h --

#defineIDC_EDIT11000
# define IDC_BUTTON 11001
# define IDC_EDIT21002
# define IDC_EDIT3 1003

--bugcheck.rc --

IDD_BUGCHECK_DIALOG DIALOGEX 0,0,202,129
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
EXSTYLE WS_EX_APPWINDOW
CAPTION "bugcheck"
FONT9, "MS UI Gothic", 0, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK", IDOK, 67, 91, 50, 14
PUSHBUTTON "Cancel", IDCANCEL, 121, 91, 50, 14
EDITTEXT IDC_EDIT1,44,31,40,14,ES_AUTOHSCROLL
PUSHBUTTON "UpdateData(false), IDC_BUTTON 1,99, 33, 63, 14
EDITTEXT IDC_EDIT 2, 44, 52, 40, 14, ES_AUTOHSCROLL
EDITTEXT IDC_EDIT3, 44, 71, 40, 14, ES_AUTOHSCROLL | ES_READONLY
LTEXT "f1", IDC_STATIC, 28, 34, 8, 8
LTEXT "f2", IDC_STATIC, 29, 55, 8, 8
LTEXT "f3", IDC_STATIC, 30, 75, 8, 8
END

--So much for the source --

c++ visual-studio mfc

2022-09-29 22:24

2 Answers

DDX_Text(...,double&)AfxTextFloatFormat() seems to be acting strangely.
Reproduce it in the Win32 console application below, even if it is not an MFC.

#include<stdio.h>
# include <stdlib.h>
# include <tchar.h>

int main()
{
    constintTEXT_BUFFER_SIZE=400;
    TCHARszBuffer [TEXT_BUFFER_SIZE] =_T("2.3");
    double;
    if(_sntscanf_s(szBuffer,_countof(szBuffer),_T("%lf"), &d)!=1){
        return1;
    }
    else{
        _tprintf_s(_T("%f\n"),d);
    }
    _tcscpy_s(szBuffer,_T("0"));
    if(_sntscanf_s(szBuffer,_countof(szBuffer),_T("%lf"), &d)!=1){
        return1;
    }
    else{
        _tprintf_s(_T("%f\n"),d);
    }
    return 0;
}

In Debug builds,

2.300000
0.000000

appears successfully, but in the Release build

2.300000
3.000000

appears.

All you can do is take it out with DDX_Text(...,CSstring&) and convert it to double by yourself.


2022-09-29 22:24

After reading Alpha's explanation, I looked into it a little more.

char buffer[] = {'0', '\0', '1'', '2', '3', '\0'};
double;
snscanf(buffer, std::size(buffer), "%lf", &d);

Then, it seems to pass "123" past "0\0".
This issue appears to occur in the sn version of the scanf() system that specifies the buffer size.sscanf() that does not specify a buffer size did not occur because it stops at "0\0".

If DDX_Text() is a template function or inline function, there was a workaround to redefine snscanf(), but it doesn't seem to work, so the only way is to redefine DDX_Text() directly.

Verified that bug in_sntscanf_s has been bugged and fixed in Windows 10 Build 10576. (The multi-threaded DLL must be used to build a release.)The debug build uses the DLL that came with the VS.)
In the future, the DLL will be updated in Windows Update, and the debug DLL and source code will be updated in VS2015 Update 1.


2022-09-29 22:24

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.