[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