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:
}