为什么在以下代码中mysql_init(nullptr)导致分段错误?

时间:2020-09-25 15:05:43

标签: c++ multithreading libmysql connection-pool

我的代码如下:

main.cc
int main(void){
    int port, sqlPort, ConnectionNum, threadNum;
    string sqlUser, sqlPwd, DBName;
    try{
        Config Settings("./config.ini");
        Settings.Read("port",port);
        Settings.Read("sqlPort",sqlPort);
        Settings.Read("sqlUser",sqlUser);
        Settings.Read("sqlPwd",sqlPwd);
        Settings.Read("DBName",DBName);
        Settings.Read("ConnectionNum",ConnectionNum);
        Settings.Read("threadNum",threadNum);
    }catch(File_Not_Found& e){
        cerr << "Cannot Find the Configuration File:" << e.what() << endl;
        exit(1);
    }catch(Key_Not_Found& e){
        cerr << "Cannot Find the Keyword:" << e.what() << endl;
        exit(1);
    }

    WebServer server(port, 5000, sqlPort, sqlUser, sqlPwd,DBName, ConnectionNum, threadNum );
    //server.Start();
    return 0;
}
WebServer.cc
WebServer::WebServer(int port, int timeoutMS, int sqlPort, 
        const std::string& sqlUser, const std::string& sqlPwd, 
        const std::string& dbName, int connPoolNum, int threadNum)
        :m_port(port), m_timeoutMS(timeoutMS), 
         m_epoller(new Epoller()),m_timer(new TimerHeap()){
            assert(port < 65535 && port > 1024);
            m_srcDir = get_current_dir_name();
            assert(m_srcDir);
            strncat(m_srcDir, "/resources/", 16);
            HttpConn::userCnt = 0;
            HttpConn::srcDir = m_srcDir;
            connPool->init("localhost", sqlUser, sqlPwd, dbName, sqlPort, connPoolNum);
            threadPool->start(threadNum);
            m_isRunning = InitSocket();
            if(m_isRunning){
                LOG_INFO << "===================== Server Init Success =====================";
                LOG_INFO << "Port : " << m_port << ", srcDir :" << m_srcDir;
                LOG_INFO << "threadNum : " << threadNum << ", ConnectionNum : " << connPoolNum;
                
            }else{
                LOG_FATAL << "Socket Init Failure";
            }
}
SqlConnectionPool.cc
ConnectionPool *ConnectionPool::GetInstance()
{
    static ConnectionPool connPool;
    return &connPool;
}
void ConnectionPool::init(string url, string User, string PassWord, string DBName, int Port, int MaxConn)
{
    m_url = url;
    m_Port = Port;
    m_User = User;
    m_PassWord = PassWord;
    m_DatabaseName = DBName;

    for (int i = 0; i < MaxConn; i++)
    {
        MYSQL *con = NULL;
        con = mysql_init(con);   //segmentation fault happened!!

        if (con == NULL)
        {
            LOG_FATAL << "MySQL Init Error";
        }
        con = mysql_real_connect(con, url.c_str(), User.c_str(), PassWord.c_str(), DBName.c_str(), Port, NULL, 0);

        if (con == NULL)
        {
            LOG_FATAL << "MySQL Get Real Connection Error";
        }
        connList.push_back(con);
        ++m_FreeConn;
    }

    m_MaxConn = m_FreeConn;
}

enter image description here

如上图所示,指针con始终为nullptr,这会导致分段错误。而且我编写了另一个代码来测试SqlConnectionPool.cc文件,但这一次它运行良好。

SqlConnectionPool_test.cc(部分代码)
ConnectionPool* connPool = ConnectionPool::GetInstance();
unordered_map<string, string> users;
vector<thread> thread_pool;
int main(void){
    connPool->init("localhost", "root", "123123", "zjwdb", 3306, 8);
    {
        MYSQL *mysql = NULL;
        connectionRAII mysqlcon(&mysql, connPool);
        if(mysql_query(mysql, "CREATE TABLE user_test(username VARCHAR(100) NOT NULL,passwd VARCHAR(60) NOT NULL,PRIMARY KEY ( username ));")){
            LOG_ERROR << "CREATE TABLE user_test Failed : " << mysql_error(mysql);
        }

        if(!Register("test1", "test1")){
            LOG_ERROR << "INSERT test user Failed";
        }
        if(!Register("test2", "test2")){
            LOG_ERROR << "INSERT test user Failed";
        }
        if(!Register("test3", "test3")){
            LOG_ERROR << "INSERT test user Failed";
        }

        showUsers(mysql);
    }
    CountDownLatch latch(4);
    thread_pool.emplace_back(login, "test1", "test1");
    
    thread_pool.emplace_back(login, "test5", "test5");
    
    thread_pool.emplace_back(login, "test1", "test");
    
    thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
        {
            latch.countDown();
            latch.wait();
            Register(name, passwd);
            login(name, passwd);
        }
    , std::ref(latch), "test_user1", "123123");
    thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
        {
            latch.countDown();
            latch.wait();
            Register(name, passwd);
            login(name, passwd);
        }
    , std::ref(latch), "test_user2", "123123");
    thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
        {
            latch.countDown();
            latch.wait();
            Register(name, passwd);
            login(name, passwd);
        }
    , std::ref(latch), "test_user3", "123123");
    thread_pool.emplace_back([](CountDownLatch& latch, string const& name, string const& passwd)
        {
            latch.countDown();
            latch.wait();
            Register(name, passwd);
            login(name, passwd);
        }
    , std::ref(latch), "test3", "test3");

    for(auto& th : thread_pool){
        if(th.joinable())
            th.join();
    }
    MYSQL* conn_temp = NULL;
    connectionRAII mysqlconn_temp(&conn_temp, connPool);
    showUsers(conn_temp);
    dropTheTable();
    return 0;
}

那真让我感到困惑。它是libmysql.lib的错误吗?如果是的话,我该怎么解决呢?
PS:

  1. 我的Ubuntu版本是Ubuntu-16.04,而lib版本是libmysqlclient.so.20。
  2. SqlConnectionPool_test.cc在多线程环境中运行。原因是该测试文件更有可能崩溃,因为mysql_init不是线程安全的。但是它可以完美地工作。
  3. 如果需要更多信息,请告诉我,谢谢!

0 个答案:

没有答案
相关问题