2016-11-04 62 views
0

我试图使用libmysql++ API查询数据库,到目前为止我能够成功运行一些查询。 (原因后面一些将在后面解释)在C++中关闭mysql连接时出现分段错误。如何解决?

所以一切工作正常,但只要我尝试在关闭连接和退出程序,会出现一个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; 
} 
+0

请安装valgrind并使用valgrind运行您的程序。它会帮助你找到谁造成了内存错误。 –

+0

帮你个忙,用'std :: string'替换所有'char *'。有可能这个问题会“神奇地”消失,警告也会消失。请不要在C++中编写Java风格的构造函数。使用初始化列表。 –

+0

@ChristianHackl ..我已经在Java上工作了一段时间,但在C++上我几乎是初学者。直到最近我才开始学习它。所以,你可以称之为L1干扰。 –

回答

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还有在我看来代码中的一些其他问题,但由于问题是关于分段错误我会继续关注我的答案。

+0

谢谢你的回答。它像一个魅力!如果你强调你正在谈论的其他问题,我会很高兴。 –

0

貌似内存早期损坏,在这里:

char *query; // <-- uninitialized buffer 

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

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

char query[256]; 

有一定的疑问,与太在输入到数据库(如INSERT)分段故障退出,我觉得是因为这些查询不产生一个结果集

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

+0

修好了!如果你能更精确些,我会很感激。你能否对问题的第二部分进行阐述?不管怎样,谢谢你。 :) –

+0

@RavishAhmadKhan'INSERT'查询不会产生结果集,因此根据文档['mysql_fetch_row(result)'](http://dev.mysql.com/doc/refman/5.7/en/mysql- fetch-row.html)返回NULL。 – Nikita