Ada’s take on memory safety is pretty limited. Heap allocation is explicit; there’s a procedure literally named Unchecked_Deallocation to free a pointer. It does have thread-scoped locals and arenas, but nothing like declared lifetimes or borrowing. The spec allows for GC but I believe it’s rarely offered.
It’s safer than C, but I’m not quite sure where recent specs line up against C++.
People keep repeating this nonsense without updating themselves beforehand.
EDIT: To simply education on Ada,
Yes there was an optional GC, no one ever implemented it, so in Ada2012 got removed from the standard.
Almost everything can be allocated on the stack, so a strategy is to catch exceptions of not enough stack space and retry the same function with a smaller size for the data structure.
Ada95 introduced controlled types, which is basically Ada's version of RAII, no need to call Unchecked_Deallocation outside implementation details. Hardly any different from Rust code that uses unsafe underneath.
Ada/SPARK, now part of regular Ada specification, provides theorem proving capabilities, and contracts, allowing another safety level still not available in Rust.
Additionally Ada Core is contributing improving lifetime rules for access types, to have a kind of borrow checker light, when needed.
Finally, there are still 7 Ada vendors in business, with 40 years of experience deploying Ada into safety critical scenarios.
>Ada95 introduced controlled types, which is basically Ada's version of RAII, no need to call Unchecked_Deallocation outside implementation details. Hardly any different from Rust code that uses unsafe underneath.
This is basically like C++ destructors, but the problem is there are no move semantics in Ada, so you can't implement something like unique_ptr.
I've noticed a pattern that many Ada advocates on HN don't really seem to know the language. So they often conflate SPARK with Ada (as you just did) and make unfounded claims about Ada's memory safety, portraying it as being on par with Rust.
It isn't on par, Ada has no lifetime management whatsoever. It doesn't even provide C++ style smart pointers out of the box. It is possible to implement something like shared_ptr, AdaCore even has a tutorial[1], but as the other commenter pointed out, the language doesn't provide the primitives necessary for unique_ptr.
SPARK does have something like this. In fact, in SPARK, every pointer assignment transfers the ownership. But SPARK and Ada aren't synonymous. SPARK is a formal verifier built on top of Ada. Like most such tools, it's very constraining and time-consuming. It's not something that every (or even most) Ada projects use.
Nevertheless, Ada is a perfectly good language, and it's probably safer than C++. It has some really cool features. I'm really fond of in/inout/out references (cppfront stole this), named function parameters, secondary stack, fine-grained control over records (struct) layout, etc.
However, I'm not so fond of the extreme verbosity. It isn't just because of Algol-like keywords, Pascal is less verbose than Ada. Even basic stuff like instantiating generics is very noisy:
procedure do_something is
package Integer_Vectors is new
Ada.Containers.Vectors
(Index_Type => Natural,
Element_Type => Integer);
vec : Integer_Vectors.Vector;
begin
return;
end;
What’s your sense of the size of the Ada job market? High hundreds? Close to 10,000? Is it static or growing or shrinking? Is there a preferred online community for Ada devs?
Probably a thousand max in France? extrapolating from the ones I know, if you're talking defense/aeronautics (but I don't know or see everyone). Someone from AdaCore would give a better approximate.
We (embedded company) don't hire specifically with Ada experience (it's welcome but not mandatory) we just train people and then focus on shipping stuff.
Recent work have introduced lifetimes and an ownership model into SPARK (the reduced easier-to-prove Ada subset) https://blog.adacore.com/using-pointers-in-spark and hopefully it'll trickle down soon in Ada.
Edit: there's also reference counting and controlled types of course. And the secondary stack makes many uses of heap allocation go away.
Yes the secondary stack is this thing that make many (most?) heap allocations inexistant in Ada. So when you're talking about memory safety to an Ada dev as if it was the biggest pain, they might look strangely at you.
Yes indeed, heap allocated pointers are a PITA but we don't use so many of them. In 16 years as an kinda embedded dev on multiple MLOC codebases, I can count on my fingers the times I had to reach to pointers (and unchecked_deallocation) and didn't have a safer alternative (usually Controlled scoped pointer types, but also containers, indefinite types, and if really stuck reference-counted things if really you must murky the scope - but I'd flag the last one as 'need to show why you can't just copy the data around' at code review...).
Not saying it's not missing but I wish we spent more energy on automated proof of absence of runtime errors, large-scale whole-system static analysis, and even more stringent runtime or compilation checks. And better tooling/language support around network, threading, and distributed processing, improved test and coverage tools.
It does have Rust like borrowing in SPARK subset of the language.
There was attempt to have it in Ada 2022 Standard, but it came late. Committee decided it's best not to rush and let compiler vendors implement how they think is best and go from there.
>It’s safer than C, but I’m not quite sure where recent specs line up against C++.
Ada allows to return objects of variable size, so it's not that common that you actually need to explicitly allocate stuff. The general guideline for dynamic memory allocation is:
1) Use Second stack (this is how Ada allows to return object of variable size)
2) If cant use containers
3) If cant use controlled types (RAII)
4) Only then use New.
It’s safer than C, but I’m not quite sure where recent specs line up against C++.