Faust2011 schrieb:
malloc macht doch nichts anderes, als es an das Betriebssystem zu delegieren.
Dem ist nicht so, bzw. bedingt. Die Zeiten, in denen Malloc einfach den program break versetzt hat, sind vorbei. Es kann durchaus noch sein, dass wenn man einen demnach großen Speicherbereich anfordert, unter POSIX mmap(2) verwendet wird. Aber die Freispeicherliste selbst ist z.B. für C in der C-Runtime der jeweiligen C-Standardbibliothek implementiert.
Klar ist, dass das Durchlaufen und Verwalten der Freispeicherliste Zeit kostet. Es gibt im Internet diverse Benchmarks der verschiedenen Malloc-Implementierungen, es gibt extra Bibliotheken, die für Multithreading Core-affinen Speicher liefern, etc.
Übrigens wird in der C-Spezifikation nie Stack/Heap erwähnt, sondern nur automatisch und nicht-automatisch verwalteter Speicher. Stack/Heap sind die Implementierungen dieser Konzepte.
Nun ist die Implementierung eines Arrays auf dem Stack, wenn es eine zur Compilezeit konstante Größe hat ziemlich trivial: Der Stackpointer wird einfach um die Array-Größe weiter geschoben. Der freie Bereich ist dann für das Array. Da das Array fixe Größe hat, bleibt im Code sonst alles wie es ist Hier empfiehlt es sich, mal ein bisschen Assembly anzuschauen, z.B. auf godbolt.org.
Wenn man allerdings ein VLA auf dem Stack hat, ist die Größe nicht mehr Compilezeit-Konstant. Das sorgt dafür, dass der Kompiler keine Optimierungen, die die Größe betreffen mehr einfließen lassen kann. Siehe z.B.:
https://gcc.godbolt.org/z/IMdrI9
Außerdem sind die Adressen nicht mehr Konstant, z.B. bei a[n-i] und können damit nicht zur Kompilezeit in die Assembly geschrieben werden. Da muss zur Laufzeit rumgerechnet werden.
Außerdem kann es auch sein, dass andere Code-Teile in Mitleidenschaft gezogen werden, wenn der Kompiler z.B. eine Variable nach einem VLA auf den Stack legen sollte, hat deren Adresse dasselbe Problem. Das dürften mitunter Gründe für Torvalds Aussage sein.
Generell sollte man mit VLAs sehr vorsichtig sein und sie nur benutzen, wenn man sicher weiß, dass der erforderliche Speicher vorhanden ist. Eine gängige Stack-Größe sind 8 MB. Es gibt keine Möglichkeit festzustellen, ob eine VLA-Allokation erfüllt werden kann bzw. konnte (wie z.B. bei malloc). Das Programm geht normalerweise einfach mit einem Segfault baden.