FIX: Hanging Occurs When Using CArrayRowsetID: Q191738
|
The CArrayRowset class included with the Visual C++ 6.0 OLE DB Templates might hang when retrieving data.
There are two bugs that can cause a hang to occur:
int Except(LPEXCEPTION_POINTERS lpEP)
{
EXCEPTION_RECORD* pExcept = lpEP->ExceptionRecord;
if (pExcept->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_CONTINUE_SEARCH;
BYTE* pAddress = (LPBYTE) pExcept->ExceptionInformation[1];
VirtualAlloc(pAddress, ((BYTE*)m_pTop - (BYTE*)m_pBase), MEM_COMMIT,
PAGE_READWRITE);
return EXCEPTION_CONTINUE_EXECUTION;
}
To fix both of the problems described above, you should copy the code of
the CArrayRowset template into your own .h file and rename the class. You
then need to fix the class.
The following sample demonstrates what the resultant class might look like.
The code has added C++ exception handling to throw an exception to indicate
that the end of rowset has been reached if the index value specified is too
big. If you want to avoid C++ exception handling, you may want to revise
the code to throw the access violation to the user and let the user catch
the exception and handle it.
#include <oledberr.h>
class CDBEndOfRowset
{
};
template <class T, class TRowset = CRowset>
class CArrRowset:
public CVirtualBuffer<T>,
public TRowset
{
public:
CArrRowset(int nMax = 100000) : CVirtualBuffer<T>(nMax)
{
m_nRowsRead = 0;
}
int Except(LPEXCEPTION_POINTERS lpEP)
{
EXCEPTION_RECORD* pExcept = lpEP->ExceptionRecord;
if (pExcept->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_CONTINUE_SEARCH;
BYTE* pAddress = (LPBYTE) pExcept->ExceptionInformation[1];
VirtualAlloc(pAddress, sizeof(T), MEM_COMMIT, PAGE_READWRITE);
return EXCEPTION_CONTINUE_EXECUTION;
}
T& operator[](int nRow)
{
ATLASSERT(nRow >= 0);
HRESULT hr;
T* m_pCurrent = m_pBase + m_nRowsRead;
T* pTEndofRowset = NULL;
// Retrieve the row if you haven't retrieved it already.
while ((ULONG)nRow >= m_nRowsRead)
{
m_pAccessor->SetBuffer((BYTE*)m_pCurrent);
__try
{
// Get the row.
hr = MoveNext();
if (hr == DB_S_ENDOFROWSET)
throw CDBEndOfRowset();
if (hr != S_OK)
{
*((char*)0) = 0; // Force exception.
}
}
__except(Except(GetExceptionInformation()))
{
}
m_nRowsRead++;
m_pCurrent++;
}
return *(m_pBase + nRow);
}
HRESULT Snapshot()
{
ATLASSERT(m_nRowsRead == 0);
ATLASSERT(m_spRowset != NULL);
HRESULT hr = MoveFirst();
if (FAILED(hr))
return hr;
do
{
Write(*(T*)m_pAccessor->GetBuffer());
m_nRowsRead++;
hr = MoveNext();
} while (SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET);
return (hr == DB_S_ENDOFROWSET) ? S_OK : hr;
}
// Implementation.
ULONG m_nRowsRead;
};
Microsoft has confirmed this to be a bug in the Microsoft products 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:
Q194022 INFO: Visual Studio 6.0 Service Packs, What, Where, Why
Q194295 HOWTO: Tell That Visual Studio 6.0 Service Packs Are Installed
Additional query words:
Keywords : kbservicepack kbtemplate kbOLEDB kbVC600bug kbVS600sp2 kbVS600SP1 kbVS600sp3fix
Version : winnt:6.0
Platform : winnt
Issue type : kbbug
Last Reviewed: May 19, 1999