mysql_free_result操作稍有不慎,就会造成内存问题,要不是泄漏,要不就是非法访问。先来看下通过mysql提供的client API进行数据库操作的基本过程,
在整个过程中的每一个阶段,都要去判断代码是否出错,但是并不是每一个地方都需要去调用mysql_free_result()操作的。
下面我们假设在程序的各个阶段出现问题,来看下执行mysql_free_result()是否存在问题。
代码如下:
#include
#include
#include
using namespace std;
int main()
{
MYSQL* conn;
MYSQL_RES* res;
mysql_free_result(res);
return 0;
}
执行结果如下:
ashe@macos ~/Desktop/github/test/mysql_lib $ ./test_mysql_lib
Segmentation fault: 11
上例代码中,我们并没有对指针res进行初始化,所以存在乱指向了一块非法内存,这个可以通过调试发现。如果定义时直接初始化为NULL呢,代码如下:
int main()
{
MYSQL* conn;
MYSQL_RES* res = NULL;
MYSQL_ROW row = NULL;
char* query="select * from ashe where idk>3";
mysql_free_result(res);
return 0;
}
运行:
ashe@macos ~/Desktop/github/test/mysql_lib $ ./test_mysql_lib
ashe@macos ~/Desktop/github/test/mysql_lib $ echo $?
0
ashe@macos ~/Desktop/github/test/mysql_lib $
发现没有报错,如果连续执行两次free操作呢?
如下:
int main()
{
MYSQL* conn;
MYSQL_RES* res = NULL;
MYSQL_ROW row = NULL;
char* query="select * from ashe where idk>3";
mysql_free_result(res);
mysql_free_result(res);
return 0;
}
运行结果如下:
ashe@macos ~/Desktop/github/test/mysql_lib $ ./test_mysql_lib
ashe@macos ~/Desktop/github/test/mysql_lib $ echo $?
0
依然没有问题,这里可以先得出一个结论,对于NULL指针,可以对其执行mysql_free_result操作,并且多次操作也不会出现内存错误。
代码如下:
int main()
{
MYSQL* conn;
MYSQL_RES* res = NULL;
MYSQL_ROW row = NULL;
char* query="select * from ashe where id=1";
mysql_free_result(res);
conn=mysql_init(0);
if(!mysql_real_connect(conn,"192.168.30.129","ashe","ashe","ashe",13307,NULL,0))
{
cout << mysql_errno(conn) << " " << mysql_error(conn) <row_count << endl;
mysql_free_result(res);
}
else
{
cout << mysql_errno(conn) << " " << mysql_error(conn) << endl;
}
return 0;
}
执行结果如下:
ashe@macos ~/Desktop/github/test/mysql_lib $ ./test_mysql_lib
1
ashe@macos ~/Desktop/github/test/mysql_lib $ echo $?
0
如果执行两次free操作呢,代码如下:
int main()
{
MYSQL* conn;
MYSQL_RES* res = NULL;
MYSQL_ROW row = NULL;
char* query="select * from ashe where id=1";
mysql_free_result(res);
conn=mysql_init(0);
if(!mysql_real_connect(conn,"192.168.30.129","ashe","ashe","ashe",13307,NULL,0))
{
cout << mysql_errno(conn) << " " << mysql_error(conn) <row_count << endl;
mysql_free_result(res);
mysql_free_result(res);
}
else
{
cout << mysql_errno(conn) << " " << mysql_error(conn) << endl;
}
return 0;
}
执行结果如下:
ashe@macos ~/Desktop/github/test/mysql_lib $ ./test_mysql_lib
1
test_mysql_lib(7435,0x7fff9ef58380) malloc: *** error for object 0x7fcb857005c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
ashe@macos ~/Desktop/github/test/mysql_lib $ echo $?
134
ashe@macos ~/Desktop/github/test/mysql_lib $
发现执行报错。
代码如下:
#include
#include
#include
using namespace std;
int main()
{
MYSQL* conn;
MYSQL_RES* res = NULL;
MYSQL_ROW row = NULL;
char* query="select * from ashe where idk=1";
mysql_free_result(res);
conn=mysql_init(0);
if(!mysql_real_connect(conn,"192.168.30.129","ashe","ashe","ashe",13307,NULL,0))
{
cout << mysql_errno(conn) << " " << mysql_error(conn) <row_count << endl;
mysql_free_result(res);
mysql_free_result(res);
}
else
{
cout << res <
执行如下:
ashe@macos ~/Desktop/github/test/mysql_lib $ ./test_mysql_lib
0x0
0x0
ashe@macos ~/Desktop/github/test/mysql_lib $ echo $?
0
ashe@macos ~/Desktop/github/test/mysql_lib $
- 定义MYSQL_RES指针时,必须在使用前指向NULL;
- 如果执行了正确的查询,在执行res=mysql_store_result(conn)之后,MYSQL_RES指针不能被释放两次。
所以,比较优雅的代码处理方式,如下:
#include
#include
#include
using namespace std;
int main()
{
int ret;
MYSQL* conn;
MYSQL_RES* res = NULL;
MYSQL_ROW row = NULL;
char* query="select * from ashe where id=10";
conn=mysql_init(0);
if(!mysql_real_connect(conn,"192.168.30.129","ashe","ashe","ashe",13307,NULL,0))
{
cout << mysql_errno(conn) << " " << mysql_error(conn) <