代码之家  ›  专栏  ›  技术社区  ›  Atul

MySQL连接器/c++:GETXDRIVRIVIN()从全局构造调用时崩溃

  •  1
  • Atul  · 技术社区  · 6 年前

    get_driver_instance 从全局对象的c'tor,它只是崩溃抛出异常:访问冲突读取位置。

    示例代码:

    #define CPPCONN_LIB_BUILD // Need to include this as we are linking mysql connector in static library
    #include "MySQL\Src\mysql-connector-c++-1.1.5\cppconn\driver.h"
    
    #pragma comment(lib,"MySQL\\Src\\mysql-connector-c++-1.1.5\\BLD\\driver\\Debug\\mysqlcppconn-static.lib")
    #pragma comment(lib,"MySQL\\Src\\mysql-5.6.24\\BLD\\libmysql\\Debug\\mysqlclient.lib")
    
    struct someclass
    {
        sql::Driver *m_pDriver;
    
        someclass()
        {
            /* Create a connection */
            m_pDriver= get_driver_instance(); // It crashes here
            cout << "print something";
        }
    } someclass_instance;
    
    int main(int argc, char** argv) 
    {
        // We don't need to do anything here. The problem occurs in the global class constructor which executes before main as we've defined its global instance.
    
        return 0;
    }
    

    引发的异常类似于:

    Sample.exe中0x000007F6BE17485D处的未处理异常:0xc000005: 访问冲突读取位置0x0000000000000008。

    崩溃时的Stacktrace:

    Sample.exe!std::_Tree<class std::_Tmap_traits<class sql::SQLString,class boost::shared_ptr<class sql::mysql::MySQL_Driver>,struct std::less<class sql::SQLString>,class std::allocator<struct std::pair<class sql::SQLString const ,class boost::shared_ptr<class sql::mysql::MySQL_Driver> > >,0> >::_Lbound(class sql::SQLString const &) Unknown
    Sample.exe!std::_Tree<class std::_Tmap_traits<class sql::SQLString,class boost::shared_ptr<class sql::mysql::MySQL_Driver>,struct std::less<class sql::SQLString>,class std::allocator<struct std::pair<class sql::SQLString const ,class boost::shared_ptr<class sql::mysql::MySQL_Driver> > >,0> >::lower_bound(class sql::SQLString const &) Unknown
    Sample.exe!std::_Tree<class std::_Tmap_traits<class sql::SQLString,class boost::shared_ptr<class sql::mysql::MySQL_Driver>,struct std::less<class sql::SQLString>,class std::allocator<struct std::pair<class sql::SQLString const ,class boost::shared_ptr<class sql::mysql::MySQL_Driver> > >,0> >::find(class sql::SQLString const &)    Unknown
    Sample.exe!sql::mysql::get_driver_instance_by_name(char const * const)  Unknown
    Sample.exe!sql::mysql::get_driver_instance(void)    Unknown
    Sample.exe!get_driver_instance()    Unknown
    Sample.exe!someclass::someclass() Line 72   C++
    Sample.exe!`dynamic initializer for 'obj''() Line 76    C++
    Sample.exe!_initterm(void (void) * * pfbegin, void (void) * * pfend) Line 894   C
    Sample.exe!_cinit(int initFloatingPrecision) Line 303   C
    Sample.exe!__tmainCRTStartup() Line 227 C
    Sample.exe!mainCRTStartup() Line 164    C
    

    令人惊讶的是,这种情况只发生在调试版本中。然而,这与 this 问题。 我已确保链接调试生成的连接器库。如果我实例化同一个对象 someclass_instance 但在主函数中它不会崩溃。

    注:我花了好几个小时才弄明白。这是真正的问题。在投票前,请至少尝试一次代码。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Alan Birtles    6 年前

    您不能依赖于静态初始化不同类的顺序(例如,在您的情况下,调试和发布版本之间的顺序不同)。

    这被称为 static initialization order ‘fiasco’ .

    必须避免调用静态初始化程序中的任何代码,该程序本身依赖于静态初始化。

    map of names to drivers .

    struct someclass
    {
        sql::Driver *m_pDriver;
    
        someclass()
        {
            /* Create a connection */
            m_pDriver= get_driver_instance(); // It crashes here
            cout << "print something";
        }
    
        void foo() {}
    };
    
    someclass& someclass_instance()
    {
        static someclass instance;
        return instance;
    }
    
    int main(int argc, char** argv) 
    {
        someclass_instance().foo();
        return 0;
    }
    

    请注意 someclass_instance()

    get_driver_instance_by_name (或者提交一个bug报告,让他们为你做这件事)。