Я пытаюсь создать тестовую программу, чтобы посмотреть, сработает ли у меня идея получить и сохранить данные из базы данных SQLite3 в структуре, но я сталкиваюсь с некоторыми серьезными проблемами с кодом. Во время отладки я продолжаю сталкиваться с ошибкой в заголовке. Вот полный текст окна ошибки:
Ошибка отладки!
Файл: include \ xstring
Линия: 929Выражение: недействительный нулевой указатель
Для получения информации о том, как ваша программа может вызвать утверждение
ошибка, см. документацию по Visual C ++ для подтверждений.
А вот код, я укажу, в какой строке проблема со стрелкой (<-; дополнительную помощь см. случай 2 выключателя):
#include <iostream>
#include "data_placeholder.h"#include "sqlite3.h"#include <vector>
#include <conio.h>
#include <string>
#include <sstream>
using namespace std;
void openDB(sqlite3* dBase, int iID, string table, string operation, sqlite3_stmt* statement, vector<mission>& mission_1);
void createStatement(int iID, string table, string operation, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1);
void getMResults(string sqlStr, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1);
void returnMResult(vector<mission> mResults, vector<mission>& mission_1);
int main()
{
//Define Variables
vector<mission> mission_1;
sqlite3 *dBase;
sqlite3_stmt *statement;
int pInput;
mission_1.push_back(mission());
cout << "Input a number between 1 and 3" << endl;
cout << ">";
cin >> pInput;
cout << endl;
cout << endl;
openDB(dBase, pInput, "Mission_Data", "select from", statement, mission_1);
cout << mission_1.at(0).mName << ", " << mission_1.at(0).mDesc << ", " << mission_1.at(0).mCBELevel << ", " << mission_1.at(0).mSCReq << ", " << mission_1.at(0).mMWReq << ", " << mission_1.at(0).mTLimit << ", " << mission_1.at(0).mDifficulty << ", " << mission_1.at(0).mSector << ", " << mission_1.at(0).mSystem << ", " << mission_1.at(0).mTName << ", " << mission_1.at(0).mTSClass << ", " << mission_1.at(0).mBounty << ", " << mission_1.at(0).mXarn << ", " << mission_1.at(0).mRubies << ", " << mission_1.at(0).mDiamonds << ", " << mission_1.at(0).mDraconic << ", " << mission_1.at(0).mLithium << ", " << mission_1.at(0).mPlatinum << ", " << mission_1.at(0).mUranium << ", " << mission_1.at(0).mPlutonium << ", " << mission_1.at(0).mNWaste << ", " << mission_1.at(0).mCEXP << ", " << mission_1.at(0).mItem << ", " << mission_1.at(0).mType << ", " << endl;
_getch();
}
void openDB(sqlite3* dBase, int iID, string table, string operation, sqlite3_stmt* statement, vector<mission>& mission_1)
{
sqlite3_open("scDatabase.sqlite",&dBase);
createStatement(iID, table, operation, statement, dBase, mission_1);
}
void createStatement(int iID, string table, string operation, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1)
{
stringstream ss;
ss << iID;
string sID(ss.str());
string sqlStr = "Select * From " + table + " Where ID = " + sID;
getMResults(sqlStr, statement, dBase, mission_1);
}
void getMResults(string sqlStr, sqlite3_stmt* statement, sqlite3* dBase, vector<mission>& mission_1)
{
vector<mission> mResults;
mResults.push_back(mission());
if (sqlite3_prepare_v2(dBase, sqlStr.c_str(), sqlStr.size(), &statement, 0) == SQLITE_OK)
{
int cols;
int i;
cols = sqlite3_column_count(statement);
for (i =01; i <= cols; i++)
{
switch(i)
{
case 2:
mResults.at(0).mName = string((char*)sqlite3_column_text(statement,i)); //<-- Here is the line the assert fail happens
break;
/*
case 3:
mResults.at(0).mDesc = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 4:
mResults.at(0).mCBELevel = sqlite3_column_int(statement,i);
break;
case 5:
mResults.at(0).mSCReq = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 6:
mResults.at(0).mMWReq = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 7:
mResults.at(0).mTLimit = sqlite3_column_int(statement,i);
break;
case 8:
mResults.at(0).mDifficulty = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 9:
mResults.at(0).mSector = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 10:
mResults.at(0).mSystem = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 11:
mResults.at(0).mTName = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 12:
mResults.at(0).mTSClass = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
case 13:
mResults.at(0).mBounty = sqlite3_column_int(statement,i);
break;
case 14:
mResults.at(0).mXarn = sqlite3_column_int(statement,i);
break;
case 15:
mResults.at(0).mRubies = sqlite3_column_int(statement,i);
break;
case 16:
mResults.at(0).mDiamonds = sqlite3_column_int(statement,i);
break;
case 17:
mResults.at(0).mDraconic = sqlite3_column_int(statement,i);
break;
case 18:
mResults.at(0).mLithium = sqlite3_column_int(statement,i);
break;
case 19:
mResults.at(0).mPlatinum = sqlite3_column_int(statement,i);
break;
case 20:
mResults.at(0).mNWaste = sqlite3_column_int(statement,i);
break;
case 21:
mResults.at(0).mCEXP = sqlite3_column_int(statement,i);
break;
case 22:
mResults.at(0).mItem = sqlite3_column_int(statement,i);
break;
case 23:
mResults.at(0).mType = string(reinterpret_cast<const char*>(sqlite3_column_text(statement,i)));
break;
*/
default:
break;
}
}
}
else
{
cout << "something is wrong" << endl;
}
returnMResult(mResults, mission_1);
}
void returnMResult(vector<mission>mResults, vector<mission>& mission_1)
{
mission_1.at(0) = mResults.at(0);
}
Ошибка возникает мгновенно, когда код попадает в эту строку на первой итерации цикла for. Нет ошибок компилятора, и я также попытался объединить первые три функции в одну функцию, если указатели базы данных и операторов не были переданы правильно; та же проблема.
Редактировать 2: Я уточнил, где проблема. Это связано с моим вектором структур. Я взял запрос к базе данных из ссылки, где я установил mResults.at (0) .mName, а затем добавил приведение для const unsigned char в строку, но ошибка подтверждения все еще происходит.
Изменить 3: После просмотра некоторого кода, который я сделал ранее в этом году, я выяснил, что происходит, по крайней мере, для запроса SQLite. Вы должны вызвать step для того, чтобы запрос действительно выполнялся. Поскольку я этого не делал, указатель всегда возвращался как недействительный, поскольку не было загружено ни одной строки и, следовательно, нет столбцов для запроса. Ничего плохого в моем векторе.
проблемная линия:
sqlite3_column_text(statement,i)
вернет неопределенное значение, потому что, когда я равен размеру, он выйдет за пределы.
Функция sqlite3_column_text Параметр iCol — это индекс в стиле C, который начинается с нуля, а вы пытаетесь получить индекс столбца в стиле sql, начиная с 1. Исправьте цикл так:
for (i = 0; i < cols; i++)
Я понял проблему. Я оглянулся на какой-то код, который я сделал около июня, когда работал, и начал сравнивать его с кодом, который я разместил выше. В местах, где были различия, я скопировал код в новый тест и, наконец, заставил его работать.
Проблема была в том, что я не вызывал sqlite3_step, поэтому база данных не запрашивалась. Это приводит к тому, что строка не загружается и столбцы не запрашиваются, поэтому недопустимый указатель возвращается sqlite3_column_text. Однако у Юрия был смысл в том, что я выполнял итерацию таким образом, что, если бы ошибка, которую я получал, была исправлена, я бы начал выходить за пределы, я не смог заставить код пройти так далеко, так что немного упреждающей отладки.
Я также добавил проверки для некоторого базового защитного кодирования, чтобы тестовое приложение не сохранялось, если не загружена ни строка, ни неверный указатель, чтобы среда выполнения не выгоняла программу.