At least for the Stack, as used for subroutine handling (return address as well as parameter passing and local variables) ZMMD might be the first.
Bauer and Samelson, at the University of Munich started building a Compiler using the recent 'invented' stack principle in 1955 for the PERM, a back then tube computer. The stack principle was not only used to manage subroutines, but also as a method to compile the source code. This led in 1956 to a cooperation between the Universities of Zurich, Munich, Mainz and Darmstadt (hence the name). The idea was to create a language that could be used to compile programs for various machines from a single source.
In 1958 this led to an ACM conference in Zurich, where the concept was formalized and agreed as a standard called International Algebraic Language (IAL), later to be known as ALGOL-58.
First implementations where made for
In fact, for the Zuse, Algol became somewhat like BASIC on later home computers, as it stayed true to the idea of not using binary code, but compilation at execution. The Z23 (transistorized version of the Z22) was delivered by default with an Algol compiler as part of the OS memory (Drum). Programs to be executed were loaded from external memory (punch card, punch tape, magnetic tape) and compiled each time they were used.
Algol is often named the first 'modern' language. C is a true descendant of Algol with its change of keywords into symbols and some hardware-specific addons as notable differences.
Memory management like the C heap was also envisioned with Algol, but not implemented, as the very first machines simply hadn't enough memory available to make frivolous use of precious global memory :) But it did allow to allocate dynamic stack memory at runtime (*1).
This changed dramatically during the early 1960s, as computers switched from drums to core - and core in huge sizes, sometimes 64 KiB and more :)
PL/1 might be the first, at least the first major language to implement a heap management. It got introduced in 1966 with IBM's PL/1 for the /360 (*2). Algol added support for dynamic allocation about the same time, officially with it's Algol-68 standard, where also a
heap keyword was added to allocate heap memory for a structure (*3).
Fun fact for C: There is next to no C program without an ASCII backslash (
\) character, but it was Algol that made ANSI to introduce it to its September 1961 version, so the special Algol operators
∧ (AND) and
∨ (OR) could be spelled using a digraph of ASCII characters (
\/) - not to mention that C, as Algol's grandchild, did support them in addition to
| -- at least in early versions.
Which in turn shows why Unicode is such a great idea, as it gave back all the great mathematical operators early programming languages used, including Ac and Vel.
*1 - This did not only go well with its creators idea of a nicely nested program and data structure, but also was highly efficient and provided automatic garbage collection. Everything allocated on the stack was automatically cleaned when leaving a procedure, so any need for dynamic memory was satisfied by the stack, due to this nature of only being accessible to code on the same or lower level of nesting, and automatic cleaning when leaving.
After all, the heap is as evil as any other global variable, isn't it?
*2 - An early example how bloaty software developed by committee can be - to fit the compiler into back then well suited 64 KiB machines, it had to be split into almost 100 overlays swapped in during a single compile run.
*3 - Unlike next to all of its offspring, Algol could allocate dynamic runtime memory from the stack as well as from a heap.
REF ASTRUCT foo = LOC ASTRUCT;
allocates an ASTRUCT size chunk on the (local) stack, while
REF ASTRUCT bar = HEAP ASTRUCT;
requests a similar one from the (global) heap.
There was only one heap. Allocation from user pools wasn't supported (as always it could be handled as some kind of array of structures by the program itself).