"" gives an empty string, while "".idup gives null

simendsjo simendsjo at gmail.com
Wed Aug 3 09:50:03 PDT 2011


On 03.08.2011 18:18, Jonathan M Davis wrote:
> On Thursday 04 August 2011 00:27:12 Mike Parker wrote:
>> On 8/3/2011 11:23 PM, simendsjo wrote:
>>> On 03.08.2011 15:49, bearophile wrote:
>>>> simendsjo:
>>>>> void main() {
>>>>> assert(is(typeof("") == typeof("".idup))); // both is
>>>>> immutable(char)[]
>>>>>
>>>>> assert("" !is null);
>>>>> assert("".idup !is null); // fails - s is null. Why?
>>>>> }
>>>>
>>>> I think someone has even suggested to statically forbid "is null" on
>>>> strings :-)
>>>>
>>>> Bye,
>>>> bearophile
>>>
>>> How should I test for null if not with "is null"? There is a difference
>>> between null and empty, and avoiding this is not necessarily easy or
>>> even wanted.
>>> I couldn't find anything in the specification stating this difference.
>>> So... Is it a bug?
>>
>> This is apparently a bug. Somehow, the idup is clobbering the pointer.
>> You can see it more clearly here:
>>
>> void main()
>> {
>> 	assert("".ptr);
>>
>> 	auto s = "".idup;
>> 	assert(s.ptr); // boom!
>> }
>
> I don't know if it's a bug or not. The string _was_ duped. assert(s == "")
> passes. So, as far as equality goes, they're equal, and they don't point to
> the same memory. Now, you'd think that the new string would be just empty
> rather than null, but whether it's a bug or not depends exactly on what dup
> and idup are supposed to do with regards to null. It's probably just a side
> effect of how dup and idup are implemented rather than it being planned one way
> or the other. I don't know if it matters or not though. In general, I don't
> like the conflation of null and empty, but is this particular case, you _do_
> get a string which is equal to the original and which doesn't point to the
> same memory. So, I don't know whether this should be considered a bug or not.
> It depends on what dup and idup are ultimately supposed to do.
>
> - Jonathan M Davis

I would think it's a bug, but strings doesn't quite behave as regular 
references anyway...
But why should dup/idup change the semantics of the array?

void main() {
     // A null string or empty string works as expected
     string s1;
     assert(s1           is  null);
     assert(s1.ptr       is  null);
     assert(s1           ==  ""); // We can check for empty even if it's 
null, and it's equal to ""
     assert(s1.length    ==  0);  // ...and length even if it's null
     s1 = "";
     assert(s1           !is null);
     assert(s1.ptr       !is null);
     assert(s1.length    ==  0);
     assert(s1           ==  "");

     // the same applies to null mutable arrays
     char[] s2;
     assert(s2           is  null);
     assert(s2.ptr       is  null);
     assert(s2           ==  "");
     assert(s2.length    ==  0);
     // but with .dup/.idup things is different!
     s2 = "".dup;
     //assert(s2           !is null); // fails
     //assert(s2.ptr       !is null); // fails
     assert(s2.length    ==  0); // but... s2 is null..?
     assert(s2           ==  "");
     assert(s2           ==  s1);
}


More information about the Digitalmars-d-learn mailing list