[Issue 16408] Converting char* to string with std.conv.to!string is wrong in release mode

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sun Aug 21 05:44:39 PDT 2016


https://issues.dlang.org/show_bug.cgi?id=16408

ag0aep6g at gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code
                 CC|                            |ag0aep6g at gmail.com
          Component|phobos                      |dmd
           Severity|enhancement                 |regression

--- Comment #3 from ag0aep6g at gmail.com ---
This is triggered by the -inline switch.

This is a regression. With 2.064.2 it prints "WASD" as expected. Since 2.065 it
prints "DDDD".

This seems to be related to SDL_GetKeyName reusing the buffer it returns. From
its docs [1]:

> Returns a pointer to a UTF-8 string that stays valid at least until the next call to this function.

So when calling SDL_GetKeyName it multiple times, the previous results are
strictly invalidated. In practice, they're overwritten with the newest value.

A reduction based on that:

----
import std.stdio;
import std.conv;

char[2] buffer = '\0';

const(char*) SDL_GetKeyName(char k)
{
    buffer[0] = k;
    return buffer.ptr;
}

void main()
{
    /* prints "WASD" or "DDDD" depending on -inline */
    writeln(
        to!string(SDL_GetKeyName('W')),
        to!string(SDL_GetKeyName('A')),
        to!string(SDL_GetKeyName('S')),
        to!string(SDL_GetKeyName('D')),
    );
}
----

That test case works with 2.066 and fails since 2.067. Notice that those are
different versions than for the original test case.

A further reduction reveals a wrong-code compiler bug:

----
char[1] SDL_GetKeyName_buffer;

const(char)[] SDL_GetKeyName(char k)
{
    SDL_GetKeyName_buffer[0] = k;
    return SDL_GetKeyName_buffer[];
}

void formatGeneric() {}

void formattedWrite(string strW, string strA)
{
    auto fun = ()@trusted{ return &formatGeneric; }(); /* !? */

    assert(strW == "W", strW); /* passes without -inline, fails with */
    assert(strA == "A");
}

void main()
{
    formattedWrite(
        SDL_GetKeyName('W').idup,
        SDL_GetKeyName('A').idup,
    );
}
----

That one works with 2.065 and fails since 2.066. Yet again other versions.

I'm promoting this to a regression and to a wrong-code compiler bug. When
fixing, all test cases should be checked, since they're might be multiple
things going on here.


[1] https://wiki.libsdl.org/SDL_GetKeyName

--


More information about the Digitalmars-d-bugs mailing list