0

I'm using g++.

Implemented some wrapper for my convenience to work with libmysql. Also making C/C++ compatible code.

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

And getting warning during compilation:

warning: address of local variable ‘rows’ returned [-Wreturn-local-addr]
     MYSQL_ROW rows[count];

Please help me to find what's the problem there. I can't google something relevant to my particular case.

1
  • MYSQL_ROW rows[count]; will be allocated on the stack, you need to allocate it on the heap via malloc/calloc, if it remain on the stack, the content of the variable would be undefined once you exit the function Commented Oct 11, 2019 at 6:26

3 Answers 3

2

A more C++ way to do it is to define a movable buffer type:

struct Buf {
  Buf(size_t size) : mPtr(std::make_unique<MYSQL_ROW[]>(size)), mSize(size) {}

  std::unique_ptr<MYSQL_ROW[]> mPtr;
  size_t mSize;
};

Then you can implement the function like this:

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

The big upside of this approach is that you don't have to do manual memory handling.

Sign up to request clarification or add additional context in comments.

2 Comments

Wow. That looks cool. But why didn't you use std::string tho? Anyway I need C-compatible code in order of better performance but thank you shared this snippet too
"C-compatible code" will not automatically give you better performance.
1

rows is local array to db_query_all function and will be destroyed once control exits the function thus it is undefined behavior to return reference of it.

You can dynamically allocate the memory and return reference to it.

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

Note you need to free the memory once done processing.

3 Comments

Ah... I see.. thank you for your code. So also you forgot (MYSQL_ROW *) before malloc because C++... But I'll test.. thanks again
I was thinking in terms of C :D
Since the question is asked in a C++ context, you should use new/delete instead of malloc()/free().
1

Your error message comes from this line:

MYSQL_ROW rows[count];

which means that rows will be allocated on the stack, meaning that once your function exit the content of your variable will be undefined.

You need to either :

  • allocate the variable on heap (recommended)
MYSQL_ROW rows[] = calloc(count,sizeof(MYSQL_ROW));

don't forget to free the result once you no further need it

  • pass rows from upstream as an argument
    which would require you to get the count at another step

5 Comments

Is it necessary to use calloc instead of malloc. I know basically the difference but what about this particular thing?
no real difference, you might squeeze more perfomance by using malloc as calloc is zeroing the allocated memory.
Since the question is asked in a C++ context, you should use new/delete instead of malloc()/free().
@Pibben I asked about C/C++ context. That means I write C program for C++ compiler which has more strict rules. I like I have a gap for refactoring completely to C++ eventually but now I love to work with C instead :)
@Pibben to be fair I answer from a C perspective due to the C tag

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.