Home > Net >  Segfault with snprintf (unless I redefine the value the same way just before)
Segfault with snprintf (unless I redefine the value the same way just before)

Time:09-30

First of all please excuse me, I can't reproduce the problem, it comes from a big project and when I recover the functions one by one in a more minimalist file it suddenly works (without modifying almost anything) and I can't understand where it can come from.

First of all the project contains these structures:

typedef struct {
    uint32_t x, y;
    uint16_t w, h;
    char* str;
} Text;

typedef struct {
    uint32_t last_tick;
    uint32_t delta_ms;
    float delta;
    float t_fps;
    uint16_t fps;
} Clock;

I initialize the Text structure which is present in another structure that I will call Other from an initialization function for Other like this:

other->text_frame_rate = (Text){ 0,0,0,0, (char[8]){} };

It is supposed to contain text that looks like this FPS: 60.

Then I use snprintf to write the desired text to it in another function, like this:

void _render_frame_rate(Other* other, Clock clock)
{
    snprintf(other->text_frame_rate.str, 8, "FPS: %d", clock->fps);

    ...
}

This _render_frame_rate function is itself called from another function which looks like this at the parameter level void Render_game(SDL_Renderer* renderer, Other* other, Clock* clock);

But I get a segfault unless I redefine the frame again in _render_frame_rate like this:

void _render_frame_rate(Other* other, Clock clock)
{
    other->text_frame_rate = (Text){ 0,0,0,0, (char[8]){} }; // redefine and no problem

    snprintf(other->text_frame_rate.str, 8, "FPS: %d", clock->fps);

    ...
}

And in this case, where the struct Text has been redefined it finally works.

I also checked with a printf("%p\n"); if the address of the pointer was always the same at initialization and at the display function and yes it remains the same.

I also specify that at no time is the text_frame_rate value used or modified elsewhere.

What do you think could be causing this behavior?

UPDATE: Thanks to @IanAbbott's hint I was able to solve the problem by dynamically allocating text_frame_rate like this:

other->text_frame_rate = (Text){ 0,0,0,0, NULL };
other->text_frame_rate.str = malloc(8);

CodePudding user response:

Here is one erroneous example:

void init_other_text_frame_rate(Other *other)
{
    other->text_frame_rate = (Text){0, 0, 0, 0, (char[8]){0}};
}

void render_frame_rate(Other* other, Clock clock)
{
    snprintf(other->text_frame_rate.str, 8, "FPS: %d", clock->fps);
}

void foo(Other* other, Clock clock)
{
    init_other_text_frame_rate(other, clock);
    render_frame_rate(other, clock); // invalid!
}

The lifetime of the array of char pointed to by other->text_frame_rate.str expired when init_other_text_frame_rate(other, clock); returned to foo, so its use in the call to snprintf is invalid.

  • Related