mysql - 在C中将MySQL连接保留在函数中的静态变量中(避免全局变量)

标签 mysql c g-wan

我正在用 C 创建一个 MySQL 层(在 GWAN 中运行),并试图避免将 MySQL 连接保留在全局变量中。

我的简化代码如下所示:

    #include <mysql.h>

    const char *DB_HOST = "localhost";
    const char *DB_USER = "user";
    const char *DB_PASSWORD = "pass";
    const char *DB_DATABASE = "xxx";
    const unsigned int DB_PORT = 3306;
    const char *DB_CHARACTER_SET = "utf8";
    const char *DB_SOCKET = 0;
    const unsigned long DB_CLIENT_FLAG=0;

    typedef struct DB_Data {
        //database returned data
    } DB_Data;

    //connect to database and return the connection
    MYSQL *db_connect() {

        static MYSQL *db_connection = NULL;

        if(db_connection == NULL) {

            printf(" NEW CONN \n");

            db_connection = (MYSQL *)mysql_init(NULL);

            if(!db_connection) {
                return NULL;
            }

            //connect to the database using settings
            if(mysql_real_connect(db_connection, DB_HOST, DB_USER, DB_PASSWORD, DB_DATABASE, DB_PORT, DB_SOCKET, DB_CLIENT_FLAG) == NULL) {
                return NULL;
            }

            //set character set
            if (mysql_set_character_set(db_connection, DB_CHARACTER_SET)) {
                return NULL;
            }

        }else{
            printf(" OLD CONN \n");
        }

        return db_connection;
    }

    //close the database connection
    void db_close() {

        //get connection
        MYSQL *db_connection = db_connect();

        if(db_connection != NULL) {

            printf("\n closing... \n");

            //close connection
            mysql_close(db_connection);

            //set pointer to null
            //Fail: this does not effect the static variable in db_connect()
            db_connection = NULL;
        }
    }

    //query the database
    DB_Data *db_query(char *sql, bool getResult) {

        DB_Data *rtn;
        MYSQL_ROW row = NULL;

        //create connection if not already done
        MYSQL *db_connection = db_connect();
        //db_connect();
        if(db_connection == NULL) {
            return NULL;
        }

        if(mysql_query(db_connection, sql) != 0) {
            return NULL;
        }

        if(getResult != true) {
            return NULL;
        }

        MYSQL_RES *result = mysql_store_result(db_connection);

      if(result == NULL) {
            return NULL;
      }

        while ((row = mysql_fetch_row(result))) {
            //process data
            printf("Process data \n");
        }

        mysql_free_result(result);

        return rtn;
    }

一切正常,直到我开始使用 db_close() 关闭连接。 我的代码中似乎失败的是 db_close() 中 db_connection 未设置为 NULL。 运行 db_close() 并再次运行 db_connect() 后,db_connection 的值不为 NULL,而是与第一次运行 db_connect() 时获得的值相同。

使用 mysql_close(db_connection) 关闭连接或执行查询都没有问题,因此 db_connection(由 db_connect() 返回)有效。

如果我将 db_connection 作为全局变量,那么 db_close() 也可以工作,但我试图避免全局变量。

上面的代码是简化版本。我尝试过一些方法,例如将 MYSQL ** 作为 db_connection 传递,但我还没有让它工作。

信息和/或一些示例代码会很棒!

最佳答案

首先 - 一个简单但有点“弯曲”的解决方案可能是只使用一个名为“db_action”的函数,该函数接收一个充当一种标志的整数变量: 当标志为“0”时,您尝试连接到数据库,当标志为“1”时,您将与其断开连接:

    MYSQL *db_action(int flag) {

    static MYSQL *db_connection = NULL;

    if(flag == 0 && db_connection == NULL) {

        printf(" NEW CONN \n");

        db_connection = (MYSQL *)mysql_init(NULL);

         ...
    }
    else if(flag == 1 && db_connection != NULL){
        printf("\n closing... \n");

        //close connection
        mysql_close(db_connection);

        //set pointer to null
        db_connection = NULL;
    }
    else{           
        printf(" OLD CONN \n");
    }

    return db_connection;
}

如果您确实想要使用全局变量来实现 void,则可以这样做。在我看来,连接变量应该是全局的是有意义的,因为它可能会在程序的整个运行时使用,并由不同的函数使用。在许多c/php/ruby等基础mysql教程中,他们通常使用全局变量。

我希望您了解为什么不能在 db_close 函数中将 db_connection 变量设置为 NULL。

当您在 db_connect 函数中首先声明 static MYSQL *db_connection = NULL; 时,您将创建一个新的静态变量(这意味着它仅初始化一次)并将其设置为 NULL。您可以在这里阅读更多信息:wikipedia static_variable

然后退出(您的代码退出...)db_connect 函数。现在 db_connection 变量超出了范围 - 您无法“使用”它(读取其数据或更改它)。您只能在 db_connect 函数内执行此操作。

在 db_close 中,您获得了先前的数据库连接,MYSQL *db_connection = db_connect(); 但请注意,因为您将 *db_connection 声明为 MYSQL 类型的新变量(它是指向 MYSQL 变量的指针) )它现在位于 db_close 函数的范围内 - 并且它不能影响您之前创建的静态变量 - 它们是两个完全不同的变量 - 它们仅在您调用 db_connect() 时共享相同的数据。

开发任何类型的软件时都必须了解作用域和/或堆/堆栈机制。尤其是 C/C++ 或类似语言,当您作为程序员有更多责任来管理程序中不同变量的内存分配时。在这里阅读更多相关信息:Memory allocation, Heap and Stack

汤姆。

关于mysql - 在C中将MySQL连接保留在函数中的静态变量中(避免全局变量),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26285188/

相关文章:

php - 通过使用 php 将随机数插入 mysql 表中,将条目分组为 5 个随机组

mysql - 如何测试某个时间段是否与某个时间段有重叠?

mysql - 如何更新在查询本身中查询的表?

php - 你如何在c中包含一个HTML文件

具有多个参数的php mysql查询并获得每个结果

java - 使用 JNI 从 C 调用 Java

C - 进程退出,错误代码为 3221225477

java - 来自 logcat 调试的致命信号 11 (SIGSEGV) 位于 0x00000000(代码=1)

mysql - 在 c 脚本中连接到 mysql?

c - 如何使用 Java/Scala 在内存 G-wan 中保存数据结构