Access Violation when calling CRecordset::Requery() 
Author Message
 Access Violation when calling CRecordset::Requery()

        I am currently designing a GUI for maintaining an SQL database for a
racing game.  In one function I have a loop that calculates the points that
a specific racing team received based on the drivers that they have on the
team, and the place those drivers placed in the race.  Depending on the
information in the database, and the number of times I requery the
recordset with a different filter (for example I have tried putting in
different filters and requerying before the loop is executed which causes
varied results based on the filter, and the number of times i requery), I
get an access violation at totally different times.  As long as the
variables are all the same, it will crash on the same requery, like with
the current configuration I have it always crashes on the 8th requery.  If
I modify the information in the database, like having the team's drivers in
a different order (each team has 8 drivers-- represented by fields named
Driver1, Driver2, etc-- by changing the order, I mean simply swapping the
driver number in the Driver1 field with the driver number in the Driver8
field or something like that, which should have no bearing whatsoever),
then the access violation will move to the 9th requery (which is the 1st
requery for the second team since each team has 8 drivers).  So it isn't
that the information in the field is invalid, because the information is
fine in a different field.

Anyway, the furthest I could track the crash to is in CRecordset::Close(),
on this statement:

        if (m_hstmt != SQL_NULL_HSTMT)
        {
/*this line */  AFX_SQL_SYNC(::SQLFreeStmt(m_hstmt, SQL_DROP));
                m_hstmt = SQL_NULL_HSTMT;
        }

I will post the code it crashes in, as well as the OnInitialUpdate()
function for the CRecordView class that the function is called from, and i
will clean out the code that is irrelevant:

// The offending function

void CGlobalView::OnPostRaceUpdate()
{
        int teamPoints,         // this will store the total points obtained by a
                                // team a specific race

                i,              // a counter variable

                currentRace;    // the number of the most recent race (1-17)

        CString filter;         // stores the filter string for specific queries

        char temp[10];          // used for conversion of integers to strings

        // basic initialization here
        teamPoints = 0;
        currentRace = m_pSet->m_Current_Race_Num;

        // This loop will go through all the records in the table representing the
        // race that just ended and run a for loop that calculates the total
points
        // earned by each team.  Each record in the recordset m_pRSet[x]
        // represents a different team.

        while (!m_pRSet[currentRace]->IsEOF())
        {
                teamPoints = 0;
                for(i = 1; i <= 8; i++)
                {
                        // if the driver number in this field is 0, then the team
                        // never chose a driver, and it is time to move on to
                        // the next driver in the recordset
                        if (*(raceDriver[currentRace][i]) == 0)
                                continue;

                        // create the "DriverId = x" filter, where x is the number
                        // of the current driver chosen by the current team
                        filter = "DriverId = ";
                        itoa(*(raceDriver[currentRace][i]), temp, 10);
                        filter += temp;

                        // requery the recordset with the filter, returning the
                        // record for the selected driver
                        m_pDSet->m_strFilter = filter;
                        m_pDSet->Requery();  // this is the requery it crashes on.

                        // create the "Rank = x" filter, where x is the place
                        // that the driver we have been dealing with came in at.
                        // (like 1st place, 2nd place etc.)
                        filter = "Rank = ";
                        itoa(*(raceRank[currentRace]), temp, 10);
                        filter += temp;

                        // requery the recordset with the filter, returning the
                        // record for the rank the driver came in
                        m_pPSet->m_strFilter = filter;
                        m_pPSet->Requery();

                        // if that rank was 0, then the driver wasnt in the race,
                        // skip to the next driver
                        if (*(raceRank[currentRace]) == 0)
                                continue;
                        // add the points that are associated with the place the
                        // driver came in to the total points for the team
                        teamPoints += m_pPSet->m_DriverPoints;
                }

                // update the table that contains the total points for the team,
                // and move on to the next team
                m_pRSet[currentRace]->Edit();
                m_pRSet[currentRace]->m_RacePoints = teamPoints;
                m_pRSet[currentRace]->Update();
                m_pRSet[currentRace]->MoveNext();
        }

        // here I make sure that I start over with fresh unfiltered queries for
        // use in other parts of the program

        m_pRSet[currentRace]->Requery();
        m_pDSet->m_strFilter = "";
        m_pDSet->Requery();
        m_pPSet->m_strFilter = "";
        m_pPSet->Requery();

Quote:
}

// The OnInitialUpdate function for the class the above function is called
from

void CGlobalView::OnInitialUpdate()
{

        // This portion assigns the recordsets defined in the main document of the
        // project to some member variables so that any changes made in this
        // CView class will immediately be reflected in other CViews
        CFantasyThunderDoc* pDoc = GetDocument();
        m_pSet = &pDoc->m_globalSet;
        m_pSet->m_pDatabase = pDoc->GetDatabase();
        if(!m_pSet->IsOpen())
                m_pSet->Open();

        m_pDSet = &pDoc->m_driversSet;
        m_pDSet->m_pDatabase = pDoc->GetDatabase();
        if(!m_pDSet->IsOpen())
                m_pDSet->Open();

        m_pPSet = &pDoc->m_prizesSet;
        m_pPSet->m_pDatabase = pDoc->GetDatabase();
        if(!m_pPSet->IsOpen())
                m_pPSet->Open();

        // This loop is also assigning recordsets from the main document to
        // member variables. There are 17 identical tables in the database,
        // which all contain information for a different race.  I made an array
        // of size 18 so that no one would get confused about m_pRSet[3] actually
        // applying to race 4 and not race 3.  m_pRSet[0] is set to NULL and I
        // never access it.

        for (int i = 1; i <= 17; i++)
        {
                m_pRSet[i] = &(pDoc->m_raceSet[i]);
                m_pRSet[i]->m_pDatabase = pDoc->GetDatabase();
                if(!m_pRSet[i]->IsOpen())
                        m_pRSet[i]->Open();
        }

        // once again for simplicity's sake and compact code I am assigning
        // certain fields to indexes in an array.

        raceRank[1] = &m_pDSet->m_RaceRank1;
        raceRank[2] = &m_pDSet->m_RaceRank2;
        raceRank[3] = &m_pDSet->m_RaceRank3;
        raceRank[4] = &m_pDSet->m_RaceRank4;
        raceRank[5] = &m_pDSet->m_RaceRank5;
        raceRank[6] = &m_pDSet->m_RaceRank6;
        raceRank[7] = &m_pDSet->m_RaceRank7;
        raceRank[8] = &m_pDSet->m_RaceRank8;
        raceRank[9] = &m_pDSet->m_RaceRank9;
        raceRank[10] = &m_pDSet->m_RaceRank10;
        raceRank[11] = &m_pDSet->m_RaceRank11;
        raceRank[12] = &m_pDSet->m_RaceRank12;
        raceRank[13] = &m_pDSet->m_RaceRank13;
        raceRank[14] = &m_pDSet->m_RaceRank14;
        raceRank[15] = &m_pDSet->m_RaceRank15;
        raceRank[16] = &m_pDSet->m_RaceRank16;
        raceRank[17] = &m_pDSet->m_RaceRank17;

        // Same as above, but a 2 dimensional array is used since there are
        // 17 races, each with 8 drivers per team.

        for (i = 1; i <= 17; i++)
        {
                raceDriver[i][1] = &m_pRSet[i]->m_Driver1;
                raceDriver[i][2] = &m_pRSet[i]->m_Driver2;
                raceDriver[i][3] = &m_pRSet[i]->m_Driver3;
                raceDriver[i][4] = &m_pRSet[i]->m_Driver4;
                raceDriver[i][5] = &m_pRSet[i]->m_Driver5;
                raceDriver[i][6] = &m_pRSet[i]->m_Driver6;
                raceDriver[i][7] = &m_pRSet[i]->m_Driver7;
                raceDriver[i][8] = &m_pRSet[i]->m_Driver8;
        }

        if (!m_pSet->m_pDatabase->IsOpen())
                return;
        CRecordView::OnInitialUpdate();
        if (m_pSet->IsOpen())
        {
                GetDocument()->SetTitle("Global Information");
        }

Quote:
}



Fri, 21 Jul 2000 03:00:00 GMT  
 Access Violation when calling CRecordset::Requery()

        Well, I solved my problem.  The problem was simply that I was sometimes
querying for a non-existant record, which I believe wound up causing some
memory problems.  Here is the offending segment of code:

                        // create the "Rank = x" filter, where x is the place
                        // that the driver we have been dealing with came in at.
                        // (like 1st place, 2nd place etc.)
                        filter = "Rank = ";
                        itoa(*(raceRank[currentRace]), temp, 10);
                        filter += temp;

                        // requery the recordset with the filter, returning the
                        // record for the rank the driver came in
                        m_pPSet->m_strFilter = filter;
                        m_pPSet->Requery();

                        // if that rank was 0, then the driver wasnt in the race,
                        // skip to the next driver
                        if (*(raceRank[currentRace]) == 0)
                                continue;

note that I skipped that iteration of the loop if the rank was 0 AFTER I
checked for the point value associated with a 0 ranked driver instead of
before.  Of course, there really shouldnt have been a problem-- if I run a
query looking for records that satisfy certain criteria, and no such
records exist, then there should be no records returned, instead it
returned the first record in the table.  Microsoft, if you are watching,
you ought to have the recordset be empty under those circumstances.  Oh and
another request-- how about overloading the file iostream operators for >>
and << on CString so that we can read text directly in to them from a file?
 In my opinion the most important part of the CString class is that you
can't overwrite memory.  The purpose is defeated if you have to create a
buffer just to read the text string in and then convert it to a CString,
because if the buffer you created reads in a string that is too long, the
memory is overwritten.  



Sat, 22 Jul 2000 03:00:00 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. Access Violation when calling CRecordset::Requery()

2. NTDLL.DLL Access Violation in CRecordset-derived class?

3. Access violations once OCBC/CRecordset added to console app

4. CRecordset Open Access violation

5. CRecordset - access violations

6. CRecordset access violation

7. CRecordset Access Violation

8. Access violation in CRecordset.Close()

9. Memory access violation using CRecordset and date/time fields

10. CRecordset::Requery doesn't change cursor buffer

11. CRecordset, Open, Requery

12. CRecordset::requery()

 

 
Powered by phpBB® Forum Software