zoukankan      html  css  js  c++  java
  • mysql_init调用卡住原因分析

    有同学做类似如下的操作:

    class X

    {

    public:

    X() // 类X的构造函数ctor

    {

    _mysql_handler = mysql_init(NULL);

    }
    };

    // 定义类X的全局变量

    X g_x;

    // 程序入口main函数

    int main()

    {

    。。。 。。。

    }

    看似简单的代码,但非常不幸,程序运行时,卡在了mysql_init处。语法上看不出任何破绽,原因会是什么了?

    他提供了另一个线索:不在构造函数中调用mysql_init则正常,不会卡住。结合起来分析,推断是因为mysql_init中也使用到了全局变量(另一种原因是有越界),而全局变量的初始化顺序程序是无法约定的,很有可能是因为g_x的初始化,发生在mysql_init依赖的全局变量之前。若推论成立,则mysql_init使用了未初始化的值,这是导致它卡住的根本原因。可以使用valgrind验证一下。当然,使用下列的方法应当也能奏效:全局变量相互依赖和初始化顺序的解决办法http://blog.chinaunix.net/uid-20682147-id-3245149.html),即改成:

    #define g_x x_ref()

    X& x_ref()

    {

    static X x; // 技巧就在这里

    return x;

    }

    当然,良好的习惯是尽量避免使用全局变量,实在无法避免时(如考虑到结构的复杂性),则可以考虑用上述方法规避全局变量互依赖产生的问题。

    附1:mysql_init源码

    /****************************************************************************

      Init MySQL structure or allocate one

    ****************************************************************************/

    MYSQL * STDCALL

    mysql_init(MYSQL *mysql)

    {

      if (mysql_server_init(0, NULL, NULL))

        return 0;

      if (!mysql)

      {

        if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))

        {

          set_mysql_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);

          return 0;

        }

        mysql->free_me=1;

      }

      else

        memset(mysql, 0, sizeof(*(mysql)));

      mysql->charset=default_client_charset_info;

      strmov(mysql->net.sqlstate, not_error_sqlstate);

      /*

        Only enable LOAD DATA INFILE by default if configured with

        --enable-local-infile

      */

    #if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER)

      mysql->options.client_flag|= CLIENT_LOCAL_FILES;

    #endif

    #ifdef HAVE_SMEM

      mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name;

    #endif

      mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION;

      mysql->options.report_data_truncation= TRUE;  /* default */

      /*

        By default we don't reconnect because it could silently corrupt data (after

        reconnection you potentially lose table locks, user variables, session

        variables (transactions but they are specifically dealt with in

        mysql_reconnect()).

        This is a change: < 5.0.3 mysql->reconnect was set to 1 by default.

        How this change impacts existing apps:

        - existing apps which relyed on the default will see a behaviour change;

        they will have to set reconnect=1 after mysql_real_connect().

        - existing apps which explicitely asked for reconnection (the only way they

        could do it was by setting mysql.reconnect to 1 after mysql_real_connect())

        will not see a behaviour change.

        - existing apps which explicitely asked for no reconnection

        (mysql.reconnect=0) will not see a behaviour change.

      */

      mysql->reconnect= 0;

      mysql->options.secure_auth= TRUE;

      return mysql;

    }

    附2:mysql_server_init源码

    /*

      Initialize the MySQL client library

      SYNOPSIS

        mysql_server_init()

      NOTES

        Should be called before doing any other calls to the MySQL

        client library to initialize thread specific variables etc.

        It's called by mysql_init() to ensure that things will work for

        old not threaded applications that doesn't call mysql_server_init()

        directly.

      RETURN

        0  ok

        1  could not initialize environment (out of memory or thread keys)

    */

    int STDCALL mysql_server_init(int argc __attribute__((unused)),

          char **argv __attribute__((unused)),

          char **groups __attribute__((unused)))

    {

      int result= 0;

      if (!mysql_client_init)

      {

        mysql_client_init=1;

        org_my_init_done=my_init_done;

        if (my_init()) /* Will init threads */

          return 1;

        init_client_errs();

        if (mysql_client_plugin_init())

          return 1;

        if (!mysql_port)

        {

          char *env;

          struct servent *serv_ptr __attribute__((unused));

          mysql_port = MYSQL_PORT;

          /*

            if builder specifically requested a default port, use that

            (even if it coincides with our factory default).

            only if they didn't do we check /etc/services (and, failing

            on that, fall back to the factory default of 3306).

            either default can be overridden by the environment variable

            MYSQL_TCP_PORT, which in turn can be overridden with command

            line options.

          */

    #if MYSQL_PORT_DEFAULT == 0

          if ((serv_ptr= getservbyname("mysql", "tcp")))

            mysql_port= (uint) ntohs((ushort) serv_ptr->s_port);

    #endif

          if ((env= getenv("MYSQL_TCP_PORT")))

            mysql_port=(uint) atoi(env);

        }

        if (!mysql_unix_port)

        {

          char *env;

    #ifdef __WIN__

          mysql_unix_port = (char*) MYSQL_NAMEDPIPE;

    #else

          mysql_unix_port = (char*) MYSQL_UNIX_ADDR;

    #endif

          if ((env = getenv("MYSQL_UNIX_PORT")))

    mysql_unix_port = env;

        }

        mysql_debug(NullS);

    #if defined(SIGPIPE) && !defined(__WIN__)

        (void) signal(SIGPIPE, SIG_IGN);

    #endif

    #ifdef EMBEDDED_LIBRARY

        if (argc > -1)

           result= init_embedded_server(argc, argv, groups);

    #endif

      }

      else

        result= (int)my_thread_init();         /* Init if new thread */

      return result;

    }

  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/aquester/p/9891630.html
Copyright © 2011-2022 走看看