The #0 is not within range.
Also the empty string, technically is a nil pointer. So there is no #0.
The fact that it works without range checking => pure luck.
Change settings (like optimization) or use a diff fpc version, maybe it works, maybe it crashes, maybe it crashes in fpc 9.1 (i.e. far future).
BlockWrite takes an untyped param for "buf"
Procedure BlockWrite(var f:File;const Buf;Count:Longint);
That means, blockwrite takes the address of whatever your code puts there.
If fully evaluated, this would mean:
"s[1]" first byte of the string => deref the internal pointer => crash on nil deref
"untyped param" take the address of the above
In other words
Apparently fpc just shortcuts that (lucky). "@( ptr^ )" is "ptr".
Therefore there is no crash on the nil deref.
BlockWrite apparently does not deref, if the length is zero. But that again, is just luck.