0

I am trying to query a database using the libmysql++ API and so far I am able to successfully run some queries. (reason behind some will be explained later)

So everything works fine, but as soon as I attempt at closing the connection and exiting the program, a Segmentation fault (core dumped) appears, as you can see below:

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> 

What's causing this issue and what measures do I take to resolve this?

Coming to the some queries part--there are certain queries that exit with a Segmentation fault too when fed to the database (like INSERT) which I feel is because these queries don't produce a result set and when I try to fetch rows in displayTable() or perhaps free the result set in performQuery(char *), a NULL value is encountered. Am I right in thinking this or is there some other root cause?

The code is as follows:

#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;
}
3
  • Please install valgrind and run your program with valgrind. It will help you find who caused the memory error. Commented Nov 4, 2016 at 14:14
  • Do yourself a favour and replace all char* with std::string. Chances are that the problem will "magically" disappear, as will the warnings. And please don't write Java-style constructors in C++. Use initialisation lists. Commented Nov 4, 2016 at 15:27
  • @ChristianHackl .. I have worked on Java for some time now but am pretty much a beginner at C++. It's only recently that I started learning it. So, you can call it L1 interference. Commented Nov 4, 2016 at 16:04

2 Answers 2

1

You use uninitialized pointer here:

char *query;

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

The query variable is not initialized, and points to some random memory location. Most likely somewhere in the stack segment. When you write to that location using getline you corrupt the stack. Which leads to segmentation fault.

Since the code in question does not seem to be performance critical I'd suggest to rewrite the code like this:

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

PS there are some other issues with the code in my opinion, but since the question is about segmentation fault I'll keep my answer focused.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer. It works like a charm! And I'd be really glad if you highlight those other issues that you're talking about.
0

Looks like memory corrupted early, here:

char *query;   // <-- uninitialized buffer 

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

getline reads data from the stream and stores it into the buffer. Buffer of proper length should be allocated by you. To fix it use:

char query[256];

there are certain queries that exit with a Segmentation fault too when fed to the database (like INSERT) which I feel is because these queries don't produce a result set

INSERT query doesn't produce result set, so according to the documentation mysql_fetch_row(result) returns NULL. It's the correct behavior and not a reason of Segmentation fault.

2 Comments

That fixed it! I'd really appreciate it if you could be a bit more precise. And could you shed some light on the second part of the question? Thank you, anyway. :)
@RavishAhmadKhan INSERT query doesn't produce result set, so according to the documentation mysql_fetch_row(result) returns NULL.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.