为什么我的程序在MySQL服务器不可用时崩溃 我一直在用VS 2010专业编程C++,但我一直坚持这个问题:

为什么我的程序在MySQL服务器不可用时崩溃 我一直在用VS 2010专业编程C++,但我一直坚持这个问题:,c++,mysql,visual-studio-2010,C++,Mysql,Visual Studio 2010,如果程序启动且连接良好,则加载gameactive循环,并显示玩家的高分 但当连接出现错误时,它会冻结并崩溃。我想显示一个错误,比如连接到服务器时出错,然后继续加载游戏 我确实使用了本教程: 这是我的密码: // Standad C++ includes #include <iostream> #include <cstdlib> #include <string> using namespace std; #include <string.h>

如果程序启动且连接良好,则加载gameactive循环,并显示玩家的高分

但当连接出现错误时,它会冻结并崩溃。我想显示一个错误,比如连接到服务器时出错,然后继续加载游戏

我确实使用了本教程:

这是我的密码:

// Standad C++ includes
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
#include <string.h>

// Include the Connector/C++ headers
#include "cppconn/driver.h"
#include "cppconn/exception.h"
#include "cppconn/resultset.h"
#include "cppconn/statement.h"
#include <cgl\cgl.h>
#include <cgl\core.h>
#include <core\corefile.h>

// Link to the Connector/C++ library
#pragma comment(lib, "mysqlcppconn.lib")

// Specify our connection target and credentials
const string server   = "tcp://xxx.xxx.xxx.xxx:3306";
const string username = "xxxxxxx";
const string password = "XXxxXXxxXXxx";

char myoutput[1024];
char myoutput1[1024];
char myoutput2[1024];

s_font font;
s_bitmap bmp_background;

int connectsetup()
{
    sql::Driver     *driver; // Create a pointer to a MySQL driver object
    sql::Connection *dbConn; // Create a pointer to a database connection object
    sql::Statement  *stmt;   // Create a pointer to a Statement object to hold our SQL commands
    sql::ResultSet  *res;    // Create a pointer to a ResultSet object to hold the results of any queries we run

    // Try to get a driver to use to connect to our DBMS
    try
    {
        driver = get_driver_instance();
    }
    catch (sql::SQLException e)
    {
        cout << "Could not get a database driver. Error message: " << e.what() << endl;
    }

    // Try to connect to the DBMS server
    try
    {
        dbConn = driver->connect(server, username, password);
    }
    catch (sql::SQLException e)
    {
        cout << "Could not connect to database. Error message: " << e.what() << endl;
    }

    stmt = dbConn->createStatement(); // Specify which connection our SQL statement should be executed on

    // Try to query the database
    try
    {
        stmt->execute("USE runner");              // Select which database to use. Notice that we use "execute" to perform a command.

        res = stmt->executeQuery("SELECT * FROM highscores"); // Perform a query and get the results. Notice that we use "executeQuery" to get results back
    }
    catch (sql::SQLException e)
    {
        cout << "SQL error. Error message: " << e.what() << endl;
    }

    // While there are still results (i.e. rows/records) in our result set...
    while (res->next())
    {
        // ...get each field we want and output it to the screen
        // Note: The first field/column in our result-set is field 1 (one) and -NOT- field 0 (zero)
        // Also, if we know the name of the field then we can also get it directly by name by using:
        // res->getString("TheNameOfTheField");
        //printf(myoutput,"%s %s %s",res->getString(1),res->getString(2),res->getString(3));
        strcpy(myoutput,res->getString(1).c_str());
        strcpy(myoutput1,res->getString(2).c_str());
        strcpy(myoutput2,res->getString(3).c_str());
    }

    // Clean up after ourselves
    delete res;
    delete stmt;
    delete dbConn;

    return 0;
}

void coremain()
{
    //Fullscreen, windowed of scaled?
    corefile_mountimage("res",MOUNT_DIR);
    CGL_InitVideo(1280, 720, CGL_VIDEO_NONE);
    CGL_SetTitle("CGL - Endless poepert");
    CGL_InitFont("font_heat.tga", &font);
    CGL_LoadBitmap("track1.tga",&bmp_background);
    connectsetup();
    int gameactive=1;

    int getal=atoi(myoutput);

    do {
        do {
            CGL_WaitRefresh();
            CGL_DrawBitmap(0,0,bmp_background); 
            CGL_DrawCenteredText(100,font, "%s: %d van %s score %s",myoutput,getal,myoutput1,myoutput2);
            int key,keytrig;
            CGL_GetKeys(&key,&keytrig);
            if (keytrig & CGL_INPUT_KEY_EXIT) exit(EXIT_SUCCESS);
            CGL_SwapBuffers(); 
        } while(gameactive);
        CGL_FlushGraphics();

    } while(1);
    CGL_CloseVideo();
}

问题似乎在于您的connectSetup功能。您有try/catch块,但如果出现问题,您不会执行任何操作。你只要继续前进,就好像什么都没发生一样

同时,这也是学习智能指针的好时机。这里应该使用智能指针的原因是,即使数据库连接成功,如果出现问题,您也会有后续的try/catch块。无论何时何地发出return语句,都要确保已分配的任何内容都已清除

#include <memory>
#include <string>

std::string myoutput;
std::string myoutput1;
std::string myoutput2;

int connectsetup()
{
   sql::Driver* driver;
   std::unique_ptr<sql::Connection> dbConn;
   std::unique_ptr<sql::Statement> stmt;
   std::unique_ptr<sql::ResultSet> res;

   try
   {
        driver = get_driver_instance();
        dbConn.reset(driver->connect(server, username, password))
        stmt.reset(dbConn->createStatement());         
        stmt->execute("USE runner"); 
        res.reset(stmt->executeQuery("SELECT * FROM highscores")); // Perform a query 
        while (res->next())
        {
            myoutput = res->getString(1);
            myoutput1 = res->getString(2);
            myoutput2 = res->getString(3);
        }
    }
    catch (const sql::SQLException& e)
    {
        cout << "Something went wrong with the database stuff.  Here it is: " << e.what() << endl;
        return -1;
    }
    return 0;
}
这段代码没有编译,但我试图提取您的原始代码,并使用智能指针重写它

如果这些语句中的任何一个失败,上面的代码将抛出一个异常。注意,我们通过引用而不是通过值捕获异常。还请注意,不需要删除,因为std::unique_ptr会自动执行此操作


最后,不需要字符数组-为什么要引入它们?它只使你的函数的另一部分容易被内存覆盖,即在RES>下一个循环中。

它不是C++,它是你的程序崩溃:它在哪里崩溃?附加一个调试器,看看哪一行崩溃了。它编译并工作了…这里的try/catch结构完全混乱了。您正在捕获并忽略错误,这些错误实际上应该是停止的提示,而不是盲目地继续使用一堆未初始化的变量。记住,前面的桥之类的标志意味着停止驾驶。那个么你们为什么不在数据库打开失败时立即返回呢?你不知道你可以在功能的中间发布回报吗?此外,这将是一个学习RAII的好时机,这样回归将清理任何已经创建但不再需要的东西。