0

So I'm trying to build a class that connects to a mysql database and I want to connect in the constructor and catch exceptions to handle them and not construct the class. For reasons I won't go into I need it to work this way. I have found the error in the destructor of SQLConnection.cpp when it tries to delete a pointer. This pointer is instantiated from a MySQL connector library function and every tutorial and example I've seen has it deleted at the end. It doesn't seem right to me, but I couldn't find the documentation on the function to see why this delete was there. Also when I did delete this same pointer just running some tests in main it was fine (no seg fault).

Here is the important code so far

SQLConnection.h

#ifndef SQLCONNECTION_H
#define SQLCONNECTION_H

#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>

class SQLConnection{
    private:
    sql::Driver *driver;
    const std::string IP;
    const std::string user;
    const std::string password;
    void connect();

public:
    sql::Connection *con;
    SQLConnection();
    SQLConnection(std::string inIP, std::string inUser, std::string inPassword);
    ~SQLConnection();

};
#endif

SQLConnection.cpp (the delete in the destructor causes the seg fault. When taken out it goes away. I'll show why I'm concerned with taking it out all together after this

#include "SQLConnection.h"

SQLConnection::SQLConnection() = default;

SQLConnection::SQLConnection(const std::string inIP, const std::string inUser, const std::string inPassword)
  : IP(inIP), user(inUser), password(inPassword)
  {
      try
      {
          connect();
      }
      catch(...)
      {
          throw;
      }

  }

SQLConnection::~SQLConnection(){
  if(con != nullptr){
    delete con;   //CAUSES SEG FAULT, when taken out program runs fine 
  }
}

void SQLConnection::connect(){
  try{
      driver = get_driver_instance();
      con = driver->connect(IP, user, password);
    }
    catch (sql::SQLException &e) {
        std::cout << "# ERR: SQLException in " << __FILE__;
        std::cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << '\n';
        std::cout << "# ERR: " << e.what() << '\n';
        std::cout << "# ERR: MySQL error code: " << e.getErrorCode() << '\n';
    }
    if(con)
    {
      std::cout<<"Connected!" << "\n";
    }
}

main.cpp

const std::string ip = "tcp://127.0.0.1:3306";
const std::string user = "IncorrectUser";
const std::string password = "IncorrectPass";

SQLConnection con1(ip, user, password);
std::cout << "still going" << '\n';

when this runs with incorrect login credentials it output

4 line of exceptions from catch block in connect
connected!
still going
segmentation fault (core dumped)

with correct credentials everything works fine

main.cpp without classes to test connection works fine

try{
  driver = get_driver_instance();
  con = driver->connect(IP, user, password);
}
catch(sql::SQLException &e){
  std::cout << e.what() << '\n';
if(con){
    std::cout << "connected!" << '\n';
}
delete con; 

so I guess my main question is why is it saying connected if the constructor threw an exception shouldn't the class have never come into "existence". thus it shouldn't be saying connected and call it's destructor at the end of main causing the seg fault? Also If I need to use function level try catch in the constructor to fix this can someone give me a tip on how to call a member function from an initilization list. When I tried that before I got a compiler error saying

member field connect() does not exist
ASS466uiuc
  • 11
  • 1
  • 6
  • Start by using a debugger to find out *where* the crash happens in your code. Use the debugger to look at all involved variables at the location of the crash, do they look okay? If you still can't figure it out then come back here to edit your question to include all that information. Also please take some time to read about [how to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Some programmer dude Jun 02 '17 at 02:51
  • Off topic note: You're headed toward a [Rule of Three](https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) violation that could result in a painful amount of future debugging. – user4581301 Jun 02 '17 at 03:02
  • Why don't you simply initialize **all** of your member variables, including your pointers to `nullptr`? No, calling `connect` does not initialize your variables -- Initialization means put the name of the variable in the member initialization list of the constructor. Also, there is no need to check for `nullptr` or NULL when issuing a call to `delete`. Last, the problem is not the destructor -- the destructor is showing you that you've made mistakes prior in your class. – PaulMcKenzie Jun 02 '17 at 03:21
  • @Someprogrammerdude thank you for catching the nullptr init. It fixed the seg fault. But what I don't understand is that the class is still getting constructed and destructed even when the constructor throws an exception. I printed from the destructor, and it prints at the end of the program. Why is the constructor finishing and the class being instantiated? do I absolutely need do a function level try catch in the constructor to make sure the class never exists if an exception is thrown? – ASS466uiuc Jun 02 '17 at 03:24
  • @user4581301 Yes I took out the copy/move assignment and copy constructor out of the post to shorten it. – ASS466uiuc Jun 02 '17 at 03:26
  • Looking at your code, where does the exception take you out of the constructor? Follow your logic -- you call `connect`, and inside that function you are catching the exception. Then you proceed as if nothing is wrong. Nowhere do you rethrow the exception back up to the where you called `connect`. – PaulMcKenzie Jun 02 '17 at 03:26
  • @PaulMcKenzie Disregard my last comment I'm going to rethrow it as I believe you caught the mistake – ASS466uiuc Jun 02 '17 at 03:30
  • @PaulMcKenzie Thank you so much this was my exact problem. – ASS466uiuc Jun 02 '17 at 03:46

0 Answers0