Search code examples
cglib

C - g_snprintf works in one scenario but not in another


Pretty simple situation.

I have a response pointer to struct and i want to populate its values.

In one palce it's working:

janus_audiobridge_sync_endpoint_response *response = g_malloc0(sizeof(janus_audiobridge_sync_endpoint_response));
response->error_code = JANUS_AUDIOBRIDGE_ERROR_UNKNOWN_ERROR;
g_snprintf(response->error_cause, 512, "%s - %s", "Failed to find about page with locale - ", locale_text);
return response;

However when i do basicly the same thing another method, the response->error_cause turns out to be null:

janus_audiobridge_sync_endpoint_response *response = g_malloc0(sizeof(janus_audiobridge_sync_endpoint_response));
response->error_code = 0;
response->error_code = JANUS_AUDIOBRIDGE_ERROR_UNAUTHORIZED;
g_snprintf(response->error_cause, 512, "You need to pass a valid user_secret, before you continue.");
goto plugin_response;

My question: Why does it work in one context and not another? What is the best Practive in C, to do this kind of stuff?

Thanks!

EDIT: And even weirder is that when i do:

response->error_cause = "You need to pass a valid user_secret, before you continue.";

It works on the second example, why is that?

EDIT:

As requested:

typedef struct janus_audiobridge_sync_endpoint_response {
    gint error_code;
    gchar *error_cause;
    json_t *message;
} janus_audiobridge_sync_endpoint_response;

Solution

  • It's clear from the declaration that error_cause is just a pointer, not an array.

    So it won't point at anything valid when you allocate (and clear) an instance of janus_audiobridge_sync_endpoint_response. Thus you get undefined behavior.

    To fix this, you need to allocate room for the string. In glib-land, you can use the nice g_strdup_printf() function for this:

    response->error_cause = g_strdup_printf("%s - %s", "Failed to find about page with locale - ", "foo", locale_text);
    

    Note that I added a foo to that call, your original code seems to fail to provide the proper number of arguments considering the format string, which (again!) gives you undefined behavior.

    Doing e.g. error_cause = "hello"; is always kind of safe, since that just sets the pointer in the struct to point at a static array somewhere in memory, it doesn't copy any characters. The only risk with that is that since the pointer in the struct is not const, somebody might try to modify the string which again would bring undefined behavior.