Looks like dereferencing a null pointer, but is ok???

Georg Wrede georg.wrede at nospam.org
Tue Sep 12 16:26:56 PDT 2006


Oskar Linde wrote:
> Georg Wrede wrote:
> 
>> nobody wrote:
>>
>>>>>> void main()
>>>>>> {
>>>>>>     char[] foo = (cast(char*)null)[0..10];
>>>>>> }
>>>>
>>>>
>>>> I would have expected this to cause an error!
>>>>
>>>> And if really not, what in the world is
>>>>
>>>>    (cast(char*)null)[0..10]
>>>>
>>>> supposed to mean, or return???
>>>
>>>
>>> It is an array of the first 10 char elements starting from memory 
>>> address 0.
>>
>>
>> In the ways not otherwise specified, D is alike C and C++, at least in 
>> spirit.
>>
>> Bjarne says (C++, 3rd ed. p 5.1.1) "No object is allocated with the 
>> address 0. Consequently, 0 acts as a pointer literal, indicating that 
>> a pointer doesn't refer to an object." ((I take it this means not only 
>> class object instances but anything pointable at all.))
>>
>> For some reason I got no compile time nor runtime error from this.
> 
> 
> I don't see any reason you should. Merely handling null pointers is not 
> an error.
> 
>> We're using the slice as an rvalue, so this constitutes a dereference 
>> of a null pointer. And therefore an error.
> 
> 
> It doesn't constitute a dereferencing as far as I can tell. You merely 
> define a slice starting at the address null, being 10 chars long.
> 
> Should:
> 
> char *start = null;
> int len = 10;
> 
> be illegal?
> 
>> (I seem to remember having read somewhere that modern systems don't 
>> give user programs address spaces containing the zero address (even 
>> virtually), precisely to avoid problems and pitfalls with null. Can 
>> anybody confirm this?)
>>
>> Further, since NULL is explicitly defined to not point to anything 
>> (therefore not even the address zero), at best this code attempts to 
>> return a slice out of thin air. In other words, garbage.
> 
> 
> Yes. But it never touches the garbage.
> 
>> And specifically, even if there /was/ a zero address to point to, it 
>> would still be illegal to return the slice.
> 
> 
> Why? Should it be illegal to return an invalid pointer too?
> 
>> The following program does die (in windows) with an Access Violation:
>>
>> import std.stdio;
>>
>> void main()
>> {
>>         char[] foo = (cast(char*)null)[0..10];
>>
>>     char c = foo[1];
>> }
>>
>> And we weren't even accessing foo[0]. :-)
> 
> 
> AFAIK, most OS never map the virtual memory page 0 to anything, making 
> accesses to this page illegal. With a page size of 4k, accessing 
> anything within [0..4096] will give a guaranteed page fault.
> 
>> I consider it a bug when the compiler creates such an unusable array.
>> I consider it an bug to not error on (cast(char*)null)[0..10].
> 
> 
> I humbly disagree on both points.

I humbly agree with you, on second thought. :-)

And with Sean and Regan in the other posts.

I admit I forgot that the slice is nothing more than a real estate 
property claim, and not the thing itself. (But it did look scary at 
first sight!)

I seldom need slices... which reminds me:

import std.stdio;
import std.gc;

void main()
{
	int[] ia = new int[100];
	int[] ib = ia[2..4];

	ib[0] = 666;
	ib[1] = 777;

	delete ia;

	std.gc.fullCollect();

	char[] ca = new char[400];

	writefln("ib[0]=%d and ib[1]=%d", ib[0], ib[1]);
}

which of course gives

ib[0]=-1 and ib[1]=-1

as totally expected -- by everyone else except the poor programmer, 
whose code is larger than this example. :-)

Time for Dlint, at least for the programmer who forgot to adhere to the 
Bovine rule.



More information about the Digitalmars-d-bugs mailing list