Wine Too
Wine Too

Reputation: 4655

C basics, string to pointer

I have project with 3 files. Common header contain function declaration for check mysql connection:

int conn_check(char **m_error);

Main file calls function and expect some message in m_error in case of error:

if (!conn_check(&m_error)==0)
{
 printf("%s\n", m_error);
}

And now function in which I have problem because weak knowing of pointers:

int conn_check(char **m_error)
{
int retval = 0;
char mysqlerror[255] = {0};
MYSQL *conn;
conn = mysql_init(NULL);
if (conn)
{
    if (mysql_real_connect(conn, mysql_server, mysql_user_name, mysql_password, "", (ulong)mysql_serverport, mysql_socket, 0)==NULL)
    {
        sprintf(mysqlerror, "%u: %s", mysql_errno(conn), mysql_error(conn));
        *m_error = mysqlerror;  // Problem here
        retval = -1;
    }
} else retval = -2;
mysql_close(conn);
return retval;
}

Question is how to properly assign string mysqlerror to char pointer m_error so error message can be printed through printf in main.

Upvotes: 0

Views: 198

Answers (4)

Nick Shaw
Nick Shaw

Reputation: 2113

Upon return from conn_check(), if you do the *m_error = mysqlerror; line, you'll end up with a quite possibly invalid pointer by then, as the local char array mysqlerror is not valid outside of the local function.

You'll need to pass in a pointer to a buffer and copy the string in, or duplicate the string using strdup to allocate some global memory to give you a valid pointer for returning (but if you do this, don't forget to free the memory in main() using free afterwards).

EDIT: If you choose to pass in a buffer, it's also good practice to pass in the max buffer size, so when you copy your string in, you don't overflow the buffer.

EDIT 2: A very hacky way of fixing your existing code with minimum code is of course to declare mysqlerror as static, so it is valid outside of the function. I wouldn't ever recommend doing that though, as it means the function wouldn't be thread-safe.

Upvotes: 1

Brian Roach
Brian Roach

Reputation: 76918

char **m_error means you're passing a pointer to a pointer. Presumably this is because the function already returns an int and you want to also have the text of the error. As it is, you're assigning the address of a stack variable to the pointer which you can not do.

You would need to allocate memory, assign it to the pointer, then write to it:

*m_error = calloc(255, sizeof(char));
snprintf(*m_error, 255, "%u: %s", mysql_errno(conn), mysql_error(conn));

vasprintf() will do all of it for you:

vasprintf(m_error, "%u: %s", mysql_errno(conn), mysql_error(conn));

Note that you would then need to free() this back in the calling function.

Upvotes: 2

Richard J. Ross III
Richard J. Ross III

Reputation: 55593

Here would be my solution:

char m_error[255];
if (!conn_check(&m_error)==0)
{
 printf("%s\n", m_error);
}

int conn_check(char **m_error)
{
    int retval = 0;
    char mysqlerror[255];
    MYSQL *conn;
    ...
    sprintf(mysqlerror, "%u: %s", mysql_errno(conn), mysql_error(conn));
    strcopy(*m_error, mysqlerror);
    retval = -1;
    ...
}

Upvotes: 1

perreal
perreal

Reputation: 98118

You are returning a pointer to a local variable (char mysqlerror[255]). You should define mysqlerror in your main file and call your function like:

 if (!conn_check(mysqlerror)==0)

and change the prototype:

int conn_check(char *mysqlerror)

and remove lines:

 char mysqlerror[255] = {0};
 *m_error = mysqlerror;

Upvotes: 1

Related Questions