You are currently offline, waiting for your internet to reconnect
This article was previously published under Q197448
This article has been archived. It is offered "as is" and will no longer be updated.
This article explains the consequences of altering the address assigned toa CRecordset member variable. This problem can occur when the CRecordsetclass uses numeric or decimal fields. If the internal buffer changes, thefollowing error message can occur during a call to CRecordset::Update():
String cannot be converted to number
Each field in a database that is bound to a CRecordset member variable hasa corresponding binding address stored in CRecordset::m_pvBindAddress. Thisbinding address is the location in memory where data for each field isplaced when ODBC retrieves a record. Once bound, the address of this columnmust remain valid as long as the ODBC binding remains in effect. If thisaddress changes, the CRecordset class can display the following debug TRACEmessage when retrieving a record:
Error: field address (column x) has changed
If the field in question is a high precision numeric or decimal field, thefollowing error may occur while performing a CRecordset::Update():
String cannot be converted to number
The MFC CRecordset Class Wizard binds high precision numeric and decimalfields to CString member variables. The MFC CRecordset class keeps apointer to the CString internal buffer in CRecordset::m_pvBindAddress. Ifyou modify a CString member variable, the CString class may re-allocateit's string buffer (for example, if you increase the size of the CString).If this change occurs, the address stored in CRecordset::m_pvBindAddressbecomes invalid.

For example, the CString class can reallocate its internal memory if youmake the following call to CString::Format(...):
CString strNumber;strNumber.Format( "%6.3f", 123456.123 );				
To ensure your CString buffer is large enough, pass a larger value than thedefault of 255 to the fourth parameter of RFX_Text (nMaxLength). Forexample, the following code demonstrates the before and after of anRFX_Text call:
   // BEFORE   void CMyRecordsSet::DoFieldExchange(CFieldExchange* pFX)   {      //<AngularNoBind>{{</AngularNoBind>AFX_FIELD_MAP(CTestRecords)      pFX->SetFieldType(CFieldExchange::outputColumn);      RFX_Text(pFX, _T("[UNITS]"), m_UNITS);      //}}AFX_FIELD_MAP   }   // AFTER   void CMyRecordsSet::DoFieldExchange(CFieldExchange* pFX)   {      //<AngularNoBind>{{</AngularNoBind>AFX_FIELD_MAP(CTestRecords)      pFX->SetFieldType(CFieldExchange::outputColumn);      RFX_Text(pFX, _T("[UNITS]"), m_UNITS, 1024);      //<AngularNoBind>}}</AngularNoBind>AFX_FIELD_MAP   }				
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

This bug was corrected in Visual Studio 6.0 Service Pack 3. For more information about Visual Studio service packs, please see the following articles in the Microsoft Knowledge Base:

194022 INFO: Visual Studio 6.0 Service Packs, What, Where, Why

194295 HOWTO: Tell That Visual Studio 6.0 Service Packs Are Installed
Internally, the CRecordset class checks CRecordset::m_pvBindAddress againstthe class member field buffer to ensure it has not changed. If thiscomparison fails, you get the "String cannot be converted to number" error.

The comparison is made in dbrfx.cpp on line 1049:
if (pvBind != pInfo->m_pvBindAddress){   TRACE1("Error: CString buffer (column %u) address has changed!\n",      nField);   ASSERT(FALSE);}