Wiele interesujących odpowiedzi na to „stare” pytanie, nawet niektóre stosunkowo nowe odpowiedzi, ale nie znalazłem żadnej, która wspomniałaby o tym ....
Przy prawidłowym i ostrożnym stosowaniu konsekwentne stosowanie alloca()
(być może w całej aplikacji) do obsługi małych przydziałów o zmiennej długości (lub VLA C99, jeśli są dostępne) może prowadzić do niższego ogólnego wzrostu stosu niż w innym przypadku równoważna implementacja z wykorzystaniem dużych lokalnych tablic o stałej długości . alloca()
Może więc być dobry dla twojego stosu, jeśli użyjesz go ostrożnie.
Znalazłem ten cytat w ... OK, zrobiłem go. Ale naprawdę, pomyśl o tym ....
@j_random_hacker ma rację w swoich komentarzach pod innymi odpowiedziami: Unikanie użycia alloca()
na rzecz przewymiarowanych tablic lokalnych nie czyni twojego programu bezpieczniejszym przed przepełnieniem stosu (chyba że twój kompilator jest wystarczająco stary, aby umożliwić wstawianie funkcji, które alloca()
w takim przypadku należy zastosować uaktualnić lub, chyba że używasz alloca()
pętli wewnętrznych, w takim przypadku nie powinieneś ... nie używać alloca()
pętli wewnętrznych).
Pracowałem w środowiskach desktop / server i systemach wbudowanych. Wiele systemów wbudowanych w ogóle nie korzysta ze sterty (nawet nie łączy się z obsługą), z powodów obejmujących przekonanie, że pamięć dynamicznie przydzielana jest zła z powodu ryzyka wycieków pamięci w aplikacji, która nigdy nie zawsze restartuje się przez lata lub bardziej rozsądne uzasadnienie, że pamięć dynamiczna jest niebezpieczna, ponieważ nie można z całą pewnością stwierdzić, że aplikacja nigdy nie podzieli stosu do momentu wyczerpania fałszywej pamięci. Dlatego wbudowanym programistom pozostaje niewiele alternatyw.
alloca()
(lub VLA) może być właściwym narzędziem do pracy.
Raz po raz widziałem, jak programista sprawia, że bufor przydzielany przez stos jest „wystarczająco duży, aby obsłużyć każdą możliwą sprawę”. W głęboko zagnieżdżonym drzewie wywołań wielokrotne stosowanie tego wzorca (anty -?) Prowadzi do przesadzonego użycia stosu. (Wyobraź sobie, że drzewo wywołań ma 20 poziomów głębokości, gdzie na każdym poziomie z różnych powodów funkcja ślepo przesadza bufor 1024 bajtów „po prostu dla bezpieczeństwa”, gdy generalnie użyje tylko 16 lub mniej z nich, i tylko w bardzo w rzadkich przypadkach można użyć więcej.) Alternatywą jest użyciealloca()
lub VLA i alokuj tylko tyle miejsca na stosie, ile potrzebuje Twoja funkcja, aby uniknąć niepotrzebnego obciążania stosu. Mamy nadzieję, że gdy jedna funkcja w drzewie połączeń wymaga alokacji większej niż normalna, inne w drzewie połączeń nadal używają swoich normalnych małych alokacji, a ogólne użycie stosu aplikacji jest znacznie mniejsze niż w przypadku, gdy każda funkcja ślepo nadmiernie alokuje bufor lokalny .
Ale jeśli zdecydujesz się użyć alloca()
...
Na podstawie innych odpowiedzi na tej stronie wydaje się, że VLA powinny być bezpieczne (nie łączą alokacji stosu, jeśli są wywoływane z pętli), ale jeśli używasz alloca()
, uważaj, aby nie używać go wewnątrz pętli i upewnij się, że nie można wstawić funkcji, jeśli istnieje szansa, że zostanie wywołana w pętli innej funkcji.