我正在用 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/