【问题标题】:Debug Assertion Failed: Invalid Null Pointer调试断言失败:无效的空指针
【发布时间】:2013-10-05 19:41:09
【问题描述】:

我正在尝试制作一个测试程序,看看我在结构中从 SQLite3 数据库获取和存储数据的想法是否可行,但我遇到了代码的一些主要问题。在调试时,我不断遇到标题中的错误。以下是错误窗口的全文:

调试断言失败!

文件:包含\xstring 线路:929

表达式:无效的空指针

有关您的程序如何导致断言的信息 失败,请参阅有关断言的 Visual C++ 文档。

这里是代码,我会用箭头指示问题出在哪一行(

#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 才能实际执行查询。因为我没有这样做,所以指针总是返回无效,因为没有加载行,因此没有要查询的列。我的向量没有问题。

【问题讨论】:

    标签: c++ visual-studio-2010 sqlite runtime-error null-pointer


    【解决方案1】:

    问题线:

    sqlite3_column_text(statement,i)
    

    将返回未定义的值,因为当 i 等于 size 时,它​​会超出范围。

    sqlite3_column_text 函数 iCol 参数是 C 样式索引,从零开始,而您尝试获取列索引 sql 样式从 1 开始。将循环修复为:

    for (i = 0; i < cols; i++)
    

    【讨论】:

    • 进行了更改,但是当它到达该行时仍然出错。为了进一步澄清,程序在第一次迭代中遇到案例 2 时立即出错。将更新问题。
    【解决方案2】:

    我发现了问题所在。我回顾了我在 6 月左右编写的一些代码,并开始将它与我上面发布的代码进行比较。在存在差异的地方,我将代码复制到新的测试中,我终于让它工作了。

    问题是我没有调用 sqlite3_step,所以没有查询数据库。这导致没有行被加载,因此没有要查询的列,因此 sqlite3_column_text 返回的指针无效。然而,Iuri 也有一点,我正在以某种方式迭代,如果我得到的错误被修复,就会开始超出范围,我还没有能够让代码走那么远,所以抢先调试。

    我还为一些基本的防御性编码添加了检查,以便测试应用程序在未加载行或无效指针时保存失败,以便运行时不会将程序踢出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-14
      • 2018-06-13
      • 1970-01-01
      • 2015-05-03
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多