It’s safer than C, but I’m not quite sure where recent specs line up against C++.
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.
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.
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.
It's hardly comparable 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;
In C++ that would be: void
do_something(int arg) {
std::vector<int> vec;
}
[1] - https://www.adacore.com/gems/gem-97-reference-counting-in-ad...Edit: there's also reference counting and controlled types of course. And the secondary stack makes many uses of heap allocation go away.
begin
return "Forty Two";
end Get_Answer;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.
The secondary stack would better be used for 'functions returning objects, of which you don't know the size, at call time'.
function Any_Number (A : Natural) return String is
begin
if A = 42 return "A = Quarante Deux";
end if;
return "A =" & A'Image;
end Any_Number;
Or for those allergic to begin/end function Any_Number (A : Natural) return String is (if A = 42 then "A = Quarante Deux" else "A =" & A'Image);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.