在C ++中关闭mysql连接时出现分段错误。怎么解决?

时间:2016-11-04 13:47:35

标签: c++ mysql segmentation-fault

我正在尝试使用libmysql++ API查询数据库,到目前为止,我能够成功运行一些查询。 (某些背后的原因将在稍后解释)

所以一切正常,但只要我尝试关闭连接并退出程序,就会出现Segmentation fault (core dumped),如下所示:

shell> g++ -o test testCDB.cpp -L/usr/include/mysql -lmysqlclient -I/usr/include/mysql

testCDB.cpp: In function ‘int main(int, char**)’:
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
  StudentManager manager1("localhost", "root", "ikilledkennedy.", "testDB"); 
                                                                          ^
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
testCDB.cpp:122:74: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]

shell> ./test
Successfully connected to the database.

Enter your query: SHOW DATABASES;

[information_schema]
[mysql]
[performance_schema]
[sys]
[testDB]

Do you wish to continue?(Y:1/N:0) : 1

Enter your query: SHOW TABLES;

[Student]

Do you wish to continue?(Y:1/N:0) : 0
Segmentation fault (core dumped)

shell> 

导致此问题的原因以及我采取了哪些措施来解决此问题?

来到一些查询部分 - 某些查询在提供给数据库(例如Segmentation fault)时也会以INSERT退出,我觉得这是因为这些查询不会生成结果集,当我尝试在displayTable()中获取行或者在performQuery(char *)中释放结果集时,会遇到NULL值。我是否正确地思考这个问题还是有其他根本原因?

代码如下:

#include <iostream>
#include <string>
#include <mysql.h>
#include <limits>

using namespace std;

class StudentManager
{

    private:

        char *host;
        char *user;
        char *password;
        char *database;

        MYSQL *connection;
        MYSQL_RES *result;

        void init()
        {
            connection = mysql_init(NULL); 

            if(!mysql_real_connect(connection, host, user, password, database, 0, NULL, 0))
            {
                cout << "Cannot connect to the database.\n"
                     << "Please make sure you have entered the details correctly and try again."
                     << endl;
            }

            else
            {
                cout << "Successfully connected to the database.\n" 
                     << endl;
            }       
        }

        void displayTable()
        {
            MYSQL_ROW row;

            unsigned int num_fields;
            unsigned int i;

            num_fields = mysql_num_fields(result);

            cout << endl;

            while((row = mysql_fetch_row(result)))
            {
                for(i = 0; i < num_fields; i++)
                {
                     cout << "[" << ( row[i] ? row[i] : "NULL" ) << "]";
                }

                cout << endl;
            }

            cout << endl;
        }


    public:

        StudentManager(char *host, char *user, char *password, char *database)
        {
            this->host     = host;
            this->user     = user;
            this->password = password;
            this->database = database;

            init();
        }

        void performQuery(char *query)
        {
            if(mysql_query(connection, query))
            {
                cout << "Query error: " 
                     << mysql_error(connection) 
                     << endl;

                return;
            }

            result = mysql_use_result(connection);

            displayTable();

            mysql_free_result(result);
        }


        void disconnect()
        {   
            cout << "Closing connection...";

            mysql_close(connection);

            cout << "Connection successfully closed.";
        }
};


int main(int argc, char *argv[]) 
{   

    StudentManager manager1("localhost", "foo", "bar", "testDB"); 

    int choice = 1;

    char *query;

    while(1)
    {
        cout << "Enter your query: ";
        cin.getline(query, 256); 

        manager1.performQuery(query);

        cout << "Do you wish to continue?(Y:1/N:0) : ";
        cin  >> choice;

        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        if(choice < 1)
        {   
            manager1.disconnect();

            break;
        }
    }

    return 0;
}

2 个答案:

答案 0 :(得分:0)

你在这里使用未初始化的指针:

char *query;

while(1)
{
    cout << "Enter your query: ";
    cin.getline(query, 256); 

query变量未初始化,并指向某个随机内存位置。最有可能在堆栈段的某个地方。使用getline写入该位置时,会损坏堆栈。这会导致分段错误。

由于相关代码似乎没有性能关键,我建议重写这样的代码:

std::string line;
while (cin.good())
{
    cout << "Enter your query: ";
    std::getline(cin, line);

PS我认为代码还存在其他一些问题,但由于问题是关于分段错误,我会把答案集中在一起。

答案 1 :(得分:0)

看起来内存在早期损坏,在这里:

char *query;   // <-- uninitialized buffer 

while(1)
{
  cout << "Enter your query: ";
  cin.getline(query, 256); 

getline从流中读取数据并将其存储到缓冲区中。适当长度的缓冲区应由您分配。要修复它,请使用:

char query[256];
  

某些查询在输入数据库时​​也会出现Segmentation错误(如INSERT),我觉得这些查询不会生成结果集

INSERT查询不会生成结果集,因此根据文档mysql_fetch_row(result)返回NULL。这是正确的行为,而不是Segmentation fault的原因。