Ada can manage dynamic stacks, strings and arrays on its own.
For example, Ada has what one could call type safe VLAs, instead of corrupting the stack like C, you get an exception and can redo the call with a smaller size, for example.
As for explicit heap types and Ada.Unchecked_Deallocation, yes if we are speaking about Ada 83.
Ada 95 introduced controlled types, which via Initialize, Adjust, and Finalize, provide the basis of RAII like features in Ada.
Here is an example on how to implement smart pointers with controlled types,
https://www.adacore.com/gems/gem-97-reference-counting-in-ad...
There is also the possiblity to wrap heap allocation primitives with safe interfaces exposed via storage pools, like on this tutorial https://blog.adacore.com/header-storage-pools
Finally thanks to SPARK, nowadays integrated into Ada 2012[0], you can also have formal proofs that it is safe to release heap memory.
In top of all this, Ada is in the process of integrating affine types as well.
[0] - Supported in PTC and GNAT, remaining Ada compilers have a mix of Ada 95 - 2012 features, see https://news.ycombinator.com/item?id=27603292