There are features that are inherently you-need-to-know-what-you’re-doing “unsafe” —even this version of ‘unsafe’ is typically less dangerous than, say, C’s you mistyped a symbol, gotcha!-style “unsafe”— like Unchecked_Deallocation
(guaranteed idempotent, so there is no “double free” issue), or Unchecked_Conversion
(telling the compiler use value-X of type-Y as type-Z), overlay (import+address; essentially unchecked_conversion), representation-clauses (telling the compiler “use this memory layout”), and a few other low-level features.
Insofar as memory goes, this video is excellent. I have two posts on unconstrained arrays/strings (here & here) that should be informative to one of the big, fundamental differences in Ada from other languages.
The key to really using Ada well is this: use the type-system to model your problem, then use that to solve your problem. There is a little bit of an art in designing, but that’s generally true everywhere.