libmysql:警告:返回局部变量“行”的地址 (C++/C)
libmysql: warning: address of local variable ‘rows’ returned (C++/C)
我正在使用 g++。
为方便我使用 libmysql 实现了一些包装器。同时制作 C/C++ 兼容代码。
static MYSQL_RES *db_query(MYSQL *db, const char *query, va_list params) {
char q[500];
vsprintf(q, query, params);
va_end(params);
if (mysql_query(db, q)) {
fprintf(stderr, "%s\n", mysql_error(db));
return NULL;
}
MYSQL_RES *res = mysql_use_result(db);
return res;
}
MYSQL_ROW* db_query_all(MYSQL *db, const char* query, ...) {
va_list params;
MYSQL_RES *res = db_query(db, query, params);
int count = mysql_num_rows(res);
MYSQL_ROW rows[count];
for (int i = 0; i<count; i++)
{
rows[i] = mysql_fetch_row(res);
}
mysql_free_result(res);
return rows;
}
并在编译期间收到警告:
warning: address of local variable ‘rows’ returned [-Wreturn-local-addr]
MYSQL_ROW rows[count];
请帮我找出问题所在。我无法 google 与我的具体情况相关的内容。
rows
是 db_query_all
函数的局部数组,一旦控制退出函数就会被销毁,因此它是 return 引用的未定义行为。
您可以动态分配内存并 return 引用它。
MYSQL_ROW* db_query_all(MYSQL *db, const char* query, ...) {
va_list params;
MYSQL_RES *res = db_query(db, query, params);
int count = mysql_num_rows(res);
MYSQL_ROW *rows = malloc(sizeof(*rows)*count);
for (int i = 0; i<count; i++)
{
rows[i] = mysql_fetch_row(res);
}
mysql_free_result(res);
return rows;
}
注意你需要free
内存完成处理。
您的错误信息来自这一行:
MYSQL_ROW rows[count];
这意味着 rows
将分配在堆栈上,这意味着一旦您的函数退出,您的变量的内容将是未定义的。
您需要:
- 在堆上分配变量(推荐)
MYSQL_ROW rows[] = calloc(count,sizeof(MYSQL_ROW));
不要忘记free
一旦你不再需要结果
- 将来自上游的行作为参数传递
这将需要您在另一步中获得计数
一种更 C++ 的方法是定义一个 movable 缓冲区类型:
struct Buf {
Buf(size_t size) : mPtr(std::make_unique<MYSQL_ROW[]>(size)), mSize(size) {}
std::unique_ptr<MYSQL_ROW[]> mPtr;
size_t mSize;
};
那么你可以这样实现功能:
Buf db_query_all(MYSQL *db, const char* query, ...) {
va_list params;
MYSQL_RES *res = db_query(db, query, params);
int count = mysql_num_rows(res);
Buf rows(count);
for (int i = 0; i<count; i++)
{
rows.mPtr[i] = mysql_fetch_row(res);
}
mysql_free_result(res);
return std::move(rows);
}
这种方法的一大优点是您不必进行手动内存处理。
我正在使用 g++。
为方便我使用 libmysql 实现了一些包装器。同时制作 C/C++ 兼容代码。
static MYSQL_RES *db_query(MYSQL *db, const char *query, va_list params) {
char q[500];
vsprintf(q, query, params);
va_end(params);
if (mysql_query(db, q)) {
fprintf(stderr, "%s\n", mysql_error(db));
return NULL;
}
MYSQL_RES *res = mysql_use_result(db);
return res;
}
MYSQL_ROW* db_query_all(MYSQL *db, const char* query, ...) {
va_list params;
MYSQL_RES *res = db_query(db, query, params);
int count = mysql_num_rows(res);
MYSQL_ROW rows[count];
for (int i = 0; i<count; i++)
{
rows[i] = mysql_fetch_row(res);
}
mysql_free_result(res);
return rows;
}
并在编译期间收到警告:
warning: address of local variable ‘rows’ returned [-Wreturn-local-addr]
MYSQL_ROW rows[count];
请帮我找出问题所在。我无法 google 与我的具体情况相关的内容。
rows
是 db_query_all
函数的局部数组,一旦控制退出函数就会被销毁,因此它是 return 引用的未定义行为。
您可以动态分配内存并 return 引用它。
MYSQL_ROW* db_query_all(MYSQL *db, const char* query, ...) {
va_list params;
MYSQL_RES *res = db_query(db, query, params);
int count = mysql_num_rows(res);
MYSQL_ROW *rows = malloc(sizeof(*rows)*count);
for (int i = 0; i<count; i++)
{
rows[i] = mysql_fetch_row(res);
}
mysql_free_result(res);
return rows;
}
注意你需要free
内存完成处理。
您的错误信息来自这一行:
MYSQL_ROW rows[count];
这意味着 rows
将分配在堆栈上,这意味着一旦您的函数退出,您的变量的内容将是未定义的。
您需要:
- 在堆上分配变量(推荐)
MYSQL_ROW rows[] = calloc(count,sizeof(MYSQL_ROW));
不要忘记free
一旦你不再需要结果
- 将来自上游的行作为参数传递
这将需要您在另一步中获得计数
一种更 C++ 的方法是定义一个 movable 缓冲区类型:
struct Buf {
Buf(size_t size) : mPtr(std::make_unique<MYSQL_ROW[]>(size)), mSize(size) {}
std::unique_ptr<MYSQL_ROW[]> mPtr;
size_t mSize;
};
那么你可以这样实现功能:
Buf db_query_all(MYSQL *db, const char* query, ...) {
va_list params;
MYSQL_RES *res = db_query(db, query, params);
int count = mysql_num_rows(res);
Buf rows(count);
for (int i = 0; i<count; i++)
{
rows.mPtr[i] = mysql_fetch_row(res);
}
mysql_free_result(res);
return std::move(rows);
}
这种方法的一大优点是您不必进行手动内存处理。