I am in the final stages of testing a text-based game I have been working on for several years but I am running into some major problems with my database access code and some very strange problems at that.
What I am attempting to do is loop through a SQLite3 database to get all of the data from a table and then save that data in a vector of structs for use in other classes. However when the code reaches this particular function the debugger keeps throwing out assert errors claiming there is an invalid null pointer.
What is odd here though is that I took this code and placed it into a stand-alone test program and it works perfectly. Here is that test program:
#include <iostream>
#include "../SQLite/sqlite3.h"
#include <vector>
#include <string>
using namespace std;
struct planetName
{
string pName;
};
void getPNResults(sqlite3* dBase, string operation, string table, vector<planetName> &pNames, vector<planetName> pNResults);
int getCount(string table, sqlite3* dBase);
int main()
{
vector<planetName>pNames;
vector<planetName>pNResults;
sqlite3 *dBase;
sqlite3_open("scDatabase.sqlite", &dBase);
getPNResults(dBase,"Select * From"," Planet_Names",pNames, pNResults);
cout << pNames.size() << endl << endl;
if (pNames.size() > 0)
{
for (int i = 0; i < pNames.size(); i++)
{
cout << pNames.at(i).pName << endl;
}
}
system("Pause");
}
void getPNResults(sqlite3* dBase, string operation, string table, vector<planetName> &pNames, vector<planetName> pNResults)
{
sqlite3_stmt *statement;
string sqlStr = operation + table;
if (sqlite3_prepare_v2(dBase, sqlStr.c_str(), sqlStr.size(), &statement, 0) == SQLITE_OK)
{
for (int i = 0; i < getCount("Planet_Names", dBase); i++)
{
int result = sqlite3_step(statement);
int cols = sqlite3_column_count(statement);
pNResults.push_back(planetName());
for (int i2 = 0; i2 <= cols; i2++)
{
switch(i2)
{
case 1:
pNResults.at(i).pName = string((char*)sqlite3_column_text(statement,i2));
break;
default:
break;
}
}
}
}
else
{
cout << sqlite3_errmsg(dBase) << endl;
}
for (int i = 0; i < pNResults.size(); i++)
{
pNames.push_back(planetName());
pNames.at(i).pName = pNResults.at(i).pName;
}
//pNResults.clear();
}
int getCount(string table, sqlite3* dBase)
{
string sqlStr2 = "Select Count(*) From " + table;
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(dBase, sqlStr2.c_str(), sqlStr2.size(), &statement, 0) == SQLITE_OK)
{
int result = sqlite3_step(statement);
if (result == SQLITE_ROW)
{
return sqlite3_column_int(statement,0);
}
}
}
Now here is the same code but as part of my game and where the two functions are called from:
Database.cpp:
void Database::getPNResults(bool* bErrors)
{
if (sqlite3_prepare_v2(dBase, sqlStr.c_str(), sqlStr.size(), &statement, 0) == SQLITE_OK)
{
for (i = 0; i < getCount("Planet_Names", bErrors); i++)
{
result = sqlite3_step(statement);
cols = sqlite3_column_count(statement);
pNResults.push_back(planetName());
for (i2 = 0; i2 <= cols; i2++)
{
switch(i2)
{
case 1:
pNResults.at(i).pName = string((char*)sqlite3_column_text(statement,i2));
break;
default:
break;
}
}
}
*bErrors = false;
}
else
{
*bErrors = true;
createBInfo();
d.createBReport("SQL Code 3",sqlite3_errmsg(dBase),bLocale + to_string(__LINE__),bTDate,"./SC_Log.txt");
}
}
void Database::returnPNResult(vector<planetName>& pNames)
{
for (i = 0; i < pNResults.size(); i++)
{
pNames.push_back(planetName());
pNames.at(i).pName = pNResults.at(i).pName;
}
pNResults.clear();
}
dataSystem.cpp:
else if (table == "Planet_Names")
{
if (pNames.size() > 0)
{
pNames.clear();
}
pNames.push_back(planetName());
db_ds.getPNResults(&bErrors);
db_ds.returnPNResult(pNames);
}
Here is the error:
---------------------------
Microsoft Visual C++ Runtime LibraryDebug Assertion Failed!
Program: C:\Windows\system32\MSVCP110D.dll
File: c:\program files (x86)\microsoft visual studio 11.0\vc\include\xstring
Line: 1143Expression: invalid null pointer
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.(Press Retry to debug the application)
---------------------------
Abort Retry Ignore
The last line of my code the call stack is traced to is the sqlite3_column_text line where the data is saved to the vector in case 1. I have tried about a dozen different things to deal with this. pNResults is already initialized byt he push back but I added a second one to be sure. I tried using pNames instead of pNResults but that still caused the assert. When I tried putting it in the stand alone program it worked and that really threw me off because nothing had really changed in how it was implemented.
There has to be something that I am missing. If you need any other info let me know and I will provide it.