char[] annoyance...

Regan Heath regan at netwin.co.nz
Mon Apr 10 15:22:31 PDT 2006


On Mon, 10 Apr 2006 17:42:33 +0300, Georg Wrede <georg.wrede at nospam.org>  
wrote:
> Regan Heath wrote:
>> On Mon, 10 Apr 2006 11:58:09 +1000, Derek Parnell <derek at psych.ward>  
>> wrote:
>>
>>> On Mon, 10 Apr 2006 12:23:06 +1200, Regan Heath wrote:
>>>
>>>> Take this code:
>>>>
>>>> void main()
>>>> {
>>>>     //..open a file, read line for line, on each line:
>>>>
>>>>     for(int i = 0; i < line.length-2; i++) {
>>>>         if (line[i..i+2] != "||") continue;
>>>>         //..etc..
>>>>     }
>>>> }
>>>>
>>>> There is a subtle bug. On all lines with a length of 0 or 1 it will  
>>>> give
>>>> the following error:
>>>>
>>>> Error: ArrayBoundsError line_length.d(6)
>>>>
>>>> The problem is of course the statement "i < line.length-2".  
>>>> line.length  is
>>>> unsigned, and when you - 2 from an unsigned value.. well lets just say
>>>> that it's bigger than the actual length of the line - 2.
>>>>
>>>> Of course there are plently of other ways to code this, perhaps using
>>>> foreach, but that's not the point. The point is that this code  _can_  
>>>> be
>>>> written and on the surface looks fine. Not even -w (warnings) spots  
>>>> the
>>>> signed/unsigned problem. At the very least can we get a warning for   
>>>> this?
>>>
>>>
>>> I too have tripped up on this 'bug' and it is very annoying and   
>>> surprising.
>>>
>>> However your approach to the problem might need to change...as you  
>>> state  -
>>> "On all lines with a length of 0 or 1 it will give the following   
>>> error..."
>>> - and this is because the test that you are performing is only  
>>> applicable
>>> to lines with two or more characters in them ... so make that  
>>> condition a
>>> part of the algorithm ...
>>>
>>>   if (line.length >= 2) {
>>>     for(int i = 0; i < line.length-2; i++) {
>>>       if (line[i..i+2] != "||") continue;
>>>       //..etc..
>>>     }
>>>   }
>>>   else {
>>>      // do something for short lines...
>>>   }
>>   Thanks Derek, that's exactly what I did.
>>  The point of this post isn't to get help with one specific problem  
>> but  rather to ask whether there is a solution to the underlying  
>> problem  behaviour. I suspect this behaviour will be the source of many  
>> bugs to  come and I wonder if there is a way to avoid them.
>
> First, how come you don't use this code?
>
> 	for (int i=0; i<line.length-2; i++)
> 	{
> 		if (line[i..i] == "|")
> 			if (line[i+1..i+1] == "|")
> 				continue;
> 	}
>
> It should be more than twice as fast.

Because speed wasn't important in this case (once-off console app)

> Second, isn't your code just an excellent example of why we have bounds  
> checking in D in the first place?

Bounds checking certainly helps.

> I think the obvious and clear-for-the-reader solution is to wrap that  
> code in an if:
>
> 	if (line.length > 1)
> 	{
> 		// the above code here
> 	}
>
> I can't see what would be wrong with that.

See my reply to Derek for why I think it's 'wrong'.

Regan



More information about the Digitalmars-d mailing list