libmysql: предупреждение: возвращен адрес локальной переменной 'rows' (C ++ / C) - PullRequest
0 голосов
/ 11 октября 2019

Я использую 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];

Пожалуйста, помогите мне найти в чем проблема. Я не могу найти что-то подходящее для моего конкретного случая.

Ответы [ 3 ]

2 голосов
/ 11 октября 2019

Еще один способ сделать это на C ++ - это определить подвижный тип буфера:

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);
}

Большим преимуществом этого подхода является то, что вам не нужно выполнять ручную обработку памяти.

1 голос
/ 11 октября 2019

Ваше сообщение об ошибке исходит из этой строки:

MYSQL_ROW rows[count];

, что означает, что rows будет выделено в стеке, что означает, что после выхода из функции содержимое вашей переменной будет неопределенным.

Вам необходимо:

  • выделить переменную в куче (рекомендуется)
MYSQL_ROW rows[] = calloc(count,sizeof(MYSQL_ROW));

не забудьте free результат, как только выбольше не нужно

  • передавать строки из восходящего потока в качестве аргумента
    , который потребует от вас подсчета на другом шаге
1 голос
/ 11 октября 2019

rows является локальным массивом для функции db_query_all и будет уничтожен при выходе из функции управления, поэтому возвращать ссылку на нее неопределенно,

Вы можете динамически распределять память и возвращать ссылку наэто.

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 память после завершения обработки.

...