A proper language comparison...

bearophile bearophileHUGS at lycos.com
Thu Jul 25 19:19:06 PDT 2013


Walter Bright:

> It's done by the hardware (putting a "no-access" page at the 
> end of the stack). There's nothing unsafe about it.
>
>
>> no variable-sized stack-allocated arrays that help a bit
>> created bounded collections,
>
> I don't see how that is a safety issue.

In my opinion where you allocate your data influences the 
"safety" of your program, but it's not easy for me to tell 
exactly in what direction such influence is.

If you allocate too much data on the stack this could cause stack 
overflow. As you say a stack overflow is memory safe, but if your 
program is doing something important, a sudden crash could be 
regarded as dangerous for the user. You don't want a stack 
overflow in the code that controls your car brakes (this is not a 
totally invented example).

Having variable-sized stack-allocated arrays encourages you to 
put more data on the stack, increasing the risk of stack 
overflows.

On the other hand, if you only have fixed-sized stack-allocated 
arrays, you could allocate a fixed size array on the stack and 
then use only part of it. This waste of stack space increases the 
probability of stack overflow. A variable-sized stack-allocated 
array allows you to waste no stack space, and avoid those stack 
overallocations.

If you are using a segmented stack as Rust, stack overflows 
become less probable (it becomes more like a malloc failure), 
because the stack is able to become very large when needed. I 
think Rust needs that elastic stack because in such language it's 
easy to allocate all kind of stuff on the stack (unlike in D).

- - - - - - - - - -

Ada is safer compared to D for other things. One of them is the 
little mess of integer division that D has inherited from C.

This is how the Ada compiler forces you to write a certain 
division:

procedure Strong_Typing is
   Alpha : Integer := 1;
   Beta : Integer := 10;
   Result : Float;
begin
   Result := Float (Alpha) / Float (Beta);
end Strong_Typing;


In D you could write:

int a = 1;
int b = 10;
double r = a / b;

and in r you will not see the 0.1 value. This is a C design 
mistake that I have seen bite even programmers with more than 2 
years of programming experience with C-like languages. Perhaps 
having "/" and "div" for floating point and integer divisions in 
D could avoid those bugs.

Another mistake is D inheriting the C99 semantics of % that is 
suboptimal and bug-prone.
(Both mistakes are fixed in Python3, by the way, despite I don't 
fully like the Python3 division).

- - - - - - - - - -

In Ada there is 'others' to define the value of the array items 
that you are not specifying, this removes the bugs discussed in 
Issue 3849:

declare
   type Arr_Type is array (Integer range <>) of Integer;
   A1 : Arr_Type := (1, 2, 3, 4, 5, 6, 7, 8, 9);
begin
   A1 := (1, 2, 3, others => 10);
end;


'others' is usable even for struct literals, when you don't want 
to specify all fields:

type R is record
   A, B : Integer := 0;
   C : Float := 0.0;
end record;
V3 : R => (C => 1.0, others => <>);



For D I suggested array syntax like:

int[$] a1 = [1, 2, 3];
int[10] a2 = [1, 2, 3, ...];
void main() {}

where the "..." tells the compiler the programmer wants it to 
fill those missing values with their default init.


Ada Concurrency is quite refined, and it's kind of safe.

Bye,
bearophile


More information about the Digitalmars-d mailing list