Thread overview
something weird with strerror_r
Jan 29, 2015
CodeSun
Jan 29, 2015
Adam D. Ruppe
Jan 29, 2015
Mike Parker
Jan 31, 2015
CodeSun
January 29, 2015
Recently, I found something really weird when I use strerror_t function which is declared inside std.c.string.
The code snippet is listed below:
import std.c.string;
import core.stdc.errno;

void main() {
	import std.stdio;
	char[128] buf;
	strerror_r(errno, buf.ptr, buf.sizeof);
	writeln(cast(string)buf);
}

The terminal should print "Success" with errno=0, but in this example, the result is "��������������������������������������������������������������������������������������������������������������������������������".
I test this snippet both on Archlinux and Ubuntu 14.04.1, and the result is same. If there is someone can help me?
I wanna know if it is my mistake or it is just a bug.
Thx!
January 29, 2015
On Thursday, 29 January 2015 at 14:40:32 UTC, CodeSun wrote:
> 	writeln(cast(string)buf);

Casting to string is often a mistake, here it might be the problem because you didn't check for the zero terminator, so the writeln prints all the garbage at the end of the buffer too.

I'd try something like

char[128] buf = 0; // initialize it all to zeroes

// fill it here with the function

printf("%s\n", buf.ptr); // display with printf which respects 0

and see what happens, if that works, the problem is just converting from C string back to D string, which you can do with to!string(buf.ptr) or another slicing method which is more efficient if you search for the zero yourself.
January 29, 2015
On 1/29/2015 11:40 PM, CodeSun wrote:
> Recently, I found something really weird when I use strerror_t function
> which is declared inside std.c.string.
> The code snippet is listed below:
> import std.c.string;
> import core.stdc.errno;
>
> void main() {
>      import std.stdio;
>      char[128] buf;
>      strerror_r(errno, buf.ptr, buf.sizeof);
>      writeln(cast(string)buf);
> }
>
> The terminal should print "Success" with errno=0, but in this example,
> the result is
> "��������������������������������������������������������������������������������������������������������������������������������".
>
> I test this snippet both on Archlinux and Ubuntu 14.04.1, and the result
> is same. If there is someone can help me?
> I wanna know if it is my mistake or it is just a bug.
> Thx!

The GNU version of strerror_r is documented as returning

"a pointer to a string containing the error message. This may be either a pointer to a string that the function stores in buf, or a pointer to some (immutable) static string (in which case buf is unused)."

So I think what you may have been seeing in this case is that it was returning a static string, your buffer remained empty and the writeln was printing a bunch of 0xFFs. Probably this is a better way to handle it:

void main()
{
   import core.stdc.errno : errno;
   import std.c.string : strerror_r;

   // Static arrays are initialized to T.init. For
   // char, T.init is 0xFF, *not* 0. The initializer
   // here will fill the array with 0.
   char[ 128 ] buf = 0;
   auto cstr = strerror_r( errno, buf.ptr, buf.sizeof );

   // Slice the C string with fromStringz. Unlike to!string, this
   // does not allocate or copy.
   import std.string : fromStringz;
   writeln( cstr.fromStringz() );
}
January 31, 2015
On Thursday, 29 January 2015 at 15:25:09 UTC, Mike Parker wrote:
> On 1/29/2015 11:40 PM, CodeSun wrote:
>> Recently, I found something really weird when I use strerror_t function
>> which is declared inside std.c.string.
>> The code snippet is listed below:
>> import std.c.string;
>> import core.stdc.errno;
>>
>> void main() {
>>     import std.stdio;
>>     char[128] buf;
>>     strerror_r(errno, buf.ptr, buf.sizeof);
>>     writeln(cast(string)buf);
>> }
>>
>> The terminal should print "Success" with errno=0, but in this example,
>> the result is
>> "��������������������������������������������������������������������������������������������������������������������������������".
>>
>> I test this snippet both on Archlinux and Ubuntu 14.04.1, and the result
>> is same. If there is someone can help me?
>> I wanna know if it is my mistake or it is just a bug.
>> Thx!
>
> The GNU version of strerror_r is documented as returning
>
> "a pointer to a string containing the error message. This may be either a pointer to a string that the function stores in buf, or a pointer to some (immutable) static string (in which case buf is unused)."
>
> So I think what you may have been seeing in this case is that it was returning a static string, your buffer remained empty and the writeln was printing a bunch of 0xFFs. Probably this is a better way to handle it:
>
> void main()
> {
>    import core.stdc.errno : errno;
>    import std.c.string : strerror_r;
>
>    // Static arrays are initialized to T.init. For
>    // char, T.init is 0xFF, *not* 0. The initializer
>    // here will fill the array with 0.
>    char[ 128 ] buf = 0;
>    auto cstr = strerror_r( errno, buf.ptr, buf.sizeof );
>
>    // Slice the C string with fromStringz. Unlike to!string, this
>    // does not allocate or copy.
>    import std.string : fromStringz;
>    writeln( cstr.fromStringz() );
> }

Yes, you are right, when I printed the cstr, I got the result I wanted. In fact, I neglect the detail you attached here from the manual.
Thx!