www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - something weird with strerror_r

reply "CodeSun" <cscodesun gmail.com> writes:
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!
Jan 29 2015
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Jan 29 2015
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
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() ); }
Jan 29 2015
parent "CodeSun" <cscodesun gmail.com> writes:
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!
Jan 31 2015