Frage

alloca() reserviert Speicher auf dem Stapel statt auf dem heap, wie im Fall von malloc().Also, wenn ich zurück von der routine der Speicher freigegeben wird.Also, eigentlich das löst mein problem zu befreien, dynamisch zugewiesenen Speicher.Freigabe des Speichers durch malloc() ist eine große Kopfschmerzen, und wenn Sie irgendwie verpasst führt zu allen möglichen Problemen des Gedächtnisses.

Warum ist der Einsatz von alloca() entmutigt trotz der oben genannten features?

War es hilfreich?

Lösung

Die Antwort ist direkt in der man Seite (zumindest auf Linux ):

  

UCKGABEWERT          Die alloca () Funktion gibt einen Zeiger auf den Anfang der   zugewiesenen Platz. wenn die   Zuordnung Ursachen          Stack-Überlauf, Programmverhalten ist nicht definiert.

Was nicht zu sagen, ist es sollte niemals verwendet werden. Einer der OSS-Projekten arbeite ich an nutzt es ausgiebig, und solange Sie missbrauchen sie nicht (alloca'ing große Werte), ist es in Ordnung. Sobald Sie die „paar hundert Bytes“ mark gehen vorbei, ist es Zeit malloc und Freunde zu verwenden, statt. Sie können immer noch Zuordnungsfehler, aber zumindest werden Sie einige Hinweise auf den Fehler haben, anstatt nur den Stapel ausblasen.

Andere Tipps

Einer der denkwürdigsten Fehler ich hatte, war mit einer Inline-Funktion zu tun, die alloca verwendet. Es manifestiert sich als ein Stapelüberlauf an zufälligen Punkten des Programms der Ausführung (weil es auf dem Stapel reserviert).

In der Header-Datei:

void DoSomething() {
   wchar_t* pStr = alloca(100);
   //......
}

In der Implementierungsdatei:

void Process() {
   for (i = 0; i < 1000000; i++) {
     DoSomething();
   }
}

So kam, was war die Compiler inlined DoSomething Funktion und alle Stapelzuordnungen wurden in Process() Funktion geschehen und damit den Stapel Sprengung. Zu meiner Verteidigung (und ich nicht derjenige war, der das Problem gefunden, ich hatte zu einer der leitenden Entwickler zu gehen und weinen, wenn ich es nicht beheben konnte), war es nicht gerade alloca, es war einer der ATL-String Konvertierungsmakros.

So ist die Lektion -. Nicht alloca in Funktionen, die Sie vielleicht denken inlined werden

Alte Frage, aber niemand erwähnt, dass es durch variabler Länge Arrays ersetzt werden sollte.

char arr[size];

statt

char *arr=alloca(size);

Es ist in der Standard-C99 und existierte als Compiler-Erweiterung in vielen Compilern.

alloca() ist sehr nützlich, wenn Sie nicht verwenden können eine standard-lokale variable, weil seine Größe benötigen würde, werden zur Laufzeit ermittelt und Sie können absolut garantieren, dass die Zeiger erhalten Sie von alloca() wird NIE benutzt werden, nachdem diese Funktion gibt.

Sie können sich ziemlich sicher, wenn Sie

  • nicht den Zeiger wieder, oder etwas, das es enthält.
  • bewahren Sie den Zeiger in eine beliebige Struktur auf dem heap zugeordnet
  • lassen Sie sich nicht von einem anderen thread den Zeiger verwenden

Die wirkliche Gefahr kommt aus der chance, dass jemand anderes wird gegen diese Bedingungen irgendwann später.Mit dem im Verstand, es ist toll für die Weitergabe Puffer-Funktionen formatieren von text in Ihnen :)

Wie in dieser Newsgroup Posting erwähnt, gibt es einige Gründe, warum alloca verwendet werden kann als schwierig und gefährlich:

  • Nicht alle Compiler Unterstützung alloca.
  • interpretieren Einige Compiler das beabsichtigte Verhalten von alloca unterschiedlich, so Portabilität ist nicht einmal zwischen Compiler garantiert, die es unterstützen.
  • Einige Implementierungen sind fehlerhaft.

Ein Problem ist, dass es nicht Standard ist, obwohl es weit unterstützt wird. Ceteris paribus, würde ich immer eine Standard-Funktion verwenden, anstatt eine gemeinsame Compiler-Erweiterung.

  

noch alloca Verwendung wird abgeraten, warum?

ich nicht wahrnehmen, eine solche Konsens. Viele starke Profis; ein paar Nachteile:

  • liefert C99 variabler Länge Arrays, die oft bevorzugt als die Notation der mehr im Einklang mit fester Länge Arrays und intuitiver Gesamt
  • verwendet werden würden,
  • viele Systeme haben insgesamt weniger Speicher / Adressraum für den Stack zur Verfügung, als sie für den Haufen zu tun, die das Programm etwas anfälliger für Speicher Erschöpfung macht (durch Stapelüberlauf): dies als eine gute oder eine schlechte gesehen werden kann, Sache - einer der Gründe dafür ist der Stapel nicht automatisch den Weg Haufen wachsen tut, ist out-of-Control-Programme zu verhindern, wie viel negative Auswirkungen auf die gesamte Maschine aus mit
  • , wenn sie in einem lokalen Bereich (wie ein while oder for loop) oder in verschiedenen Bereichen verwendet wird, reichert sich der Speicher pro Iteration / Umfang und wird erst die Funktion beendet Freigabe: dies steht im Gegensatz zu normalen Variablen im Umfang definiert eine Steuerstruktur (zB for {int i = 0; i < 2; ++i) { X } würde alloca-ED-Speicher in X angefordert, aber Speicher für eine feste Größe Array akkumuliert pro Iteration recycelt werden würde).
  • moderne Compiler typischerweise keine Funktionen inline die alloca nennen, aber wenn man sie zwingt, dann wird die alloca in dem Anrufer Kontext geschehen (das heißt der Stapel nicht, bis der Anrufer zurückkehrt freigegeben werden)
  • vor langer Zeit von einem nicht tragbaren Funktion transitioned alloca / Hack auf eine standardisierte Erweiterung, aber einige negative Wahrnehmung kann bestehen bleiben
  • die Lebensdauer der Funktionsumfang gebunden ist, die als die malloc explizite Kontrolle besser kann oder nicht den Programmierer passen kann
  • malloc verwenden zu müssen ermutigt über die Aufhebung der Zuordnung zu denken - wenn das durch eine Wrapper-Funktion (zB WonderfulObject_DestructorFree(ptr)) verwaltet wird, dann wird die Funktion einen Punkt für die Implementierung bietet Operationen aufzuräumen (wie Dateibeschreibungen zu schließen, zu befreien interne Zeiger oder eine Protokollierung zu tun) ohne explizite Änderungen an Client-Code: manchmal ist es ein schönes Modell konsequent zu verabschieden
    • in dieser pseudo-OO Art der Programmierung, ist es natürlich so etwas wie WonderfulObject* p = WonderfulObject_AllocConstructor(); zu wollen - das ist möglich, wenn der „Konstruktor“ ist eine Funktion malloc-ed Speicher Rückkehr (wie der Speicher zugewiesen bleibt, nachdem die Funktion den Wert zurückgibt zu speichernden in p), aber nicht, wenn der „Konstruktor“ verwendet alloca
      • eine Makro-Version von WonderfulObject_AllocConstructor dies erreichen könnte, aber „Makros sind böse“, dass können sie miteinander und nicht-Makrocode in Konflikt geraten und unbeabsichtigte Substitutionen zu erzeugen und damit schwer zu diagnostizieren Probleme
    • free Operationen fehlen kann durch valgrind nachgewiesen werden, Reinige usw. aber fehlt „destructor“ Anrufe können nicht immer alle erfasst werden - in Bezug auf die Durchsetzung der beabsichtigten Verwendung einer sehr dürftige Leistung; Einiger Implementierungen alloca() (wie GCC) verwenden, um einen Makro für inlined alloca(), so Laufzeit Substitution einer Speichernutzung Diagnose Bibliothek ist es nicht möglich, die Art und Weise ist für malloc / realloc / free (z.B. Elektrozaun)
  • einige Implementierungen haben subtile Probleme: zum Beispiel aus der Linux-Manpage:

      

    Auf vielen Systeme alloca () nicht in der Liste der Argumente eines Funktionsaufruf verwendet werden, da der Stapelspeicher von alloca reserviert () auf dem Stapel in der Mitte des Raumes für die Funktionsargumente erscheinen würde.

  •   
  

Ich weiß, diese Frage C markiert ist, sondern als ein C ++ Programmierer Ich dachte, ich C ++ verwenden würde die potentielle Nützlichkeit von alloca zu erläutern: der Code unten (und

Alle anderen Antworten sind richtig. Wenn jedoch die Sache, die Sie alloca() mit recht klein Alloc wollen, ist, glaube ich, dass es eine gute Technik ist, die schneller und bequemer ist als malloc() mit oder auf andere Weise.

Mit anderen Worten, ist alloca( 0x00ffffff ) gefährlich und wahrscheinlich Überlauf verursachen, genau so viel wie char hugeArray[ 0x00ffffff ]; ist. Seien Sie vorsichtig und vernünftig, und Sie werden in Ordnung sein.

Jeder hat bereits die große Sache, die sich aus einem Stapelüberlauf Potential nicht definiertes Verhalten, aber ich soll erwähnen, dass die Windows-Umgebung einen großen Mechanismus hat dies mit strukturierten Ausnahmen (SEH) und Wache Seiten zu fangen. Da der Stapel wächst nur bei Bedarf, befinden sich diese Wache Seiten in Bereichen, die nicht zugeordneten sind. Wenn Sie in ihnen zuteilen (durch den Stapel überfüllt) eine Ausnahme ausgelöst wird.

Sie können diese SEH Ausnahme abfangen und rufen _resetstkoflw den Stapel zurückzustellen und auf fröhliche Art und Weise fortzusetzen. Es ist nicht ideal, aber es ist ein weiterer Mechanismus zumindest etwas wissen schief gegangen ist, wenn das Material trifft den Fan. * Nichts könnte etwas ähnliches hat, dass ich nicht bewusst bin.

Ich empfehle Capping Ihre max Zuordnungsgröße von alloca Einwickeln und es intern zu verfolgen. Wenn Sie es wirklich hardcore sind, können Sie einig Umfang Posten an der Spitze Ihrer Funktion werfen alle alloca Zuweisungen im Funktionsumfang zu verfolgen und geistige Gesundheit dies überprüfen gegen den maximalen Betrag für Ihr Projekt erlaubt.

Auch zusätzlich zu erlauben nicht für Speicherlecks nicht alloca nicht Speicherfragmentierung verursachen, die ziemlich wichtig ist. Ich glaube nicht, alloca schlechte Praxis ist, wenn Sie es auf intelligente Weise zu verwenden, die für alles, was im Grunde wahr ist. : -)

alloca () ist nett und effizient ... aber es ist auch tief gebrochen.

  • gebrochen Umfang Verhalten (Funktionsumfang statt Block scope)
  • Verwendung inconsistant mit malloc ( alloca () -Ted Zeiger nicht freigegeben werden sollte, von nun an müssen Sie verfolgen, wo Sie Zeiger von kommen frei () nur diejenigen, die Sie bekam mit malloc () )
  • schlechtes Verhalten, wenn Sie auch inlining verwenden (scope geht manchmal auf die CLIP-Funktion, je nachdem ob Rufenen inlined ist oder nicht).
  • keine Stapelgrenze Prüfung
  • nicht definiertes Verhalten im Fehlerfall (nicht zurück NULL wie malloc ... und was Ausfall tut bedeutet, da es nicht Stack Grenzen überprüft sowieso ...)
  • nicht ANSI-Standard

In den meisten Fällen werden Sie es mit lokalen Variablen und majorant Größe ersetzen. Wenn es für große Objekte verwendet wird, so dass sie auf dem Heap setzt in der Regel eine sichere Idee.

Wenn Sie es wirklich brauchen C Sie VLA (keine Vla in C ++, zu schlecht) verwenden können. Sie sind viel besser als alloca () in Bezug auf Umfang Verhalten und Konsistenz. Wie ich es siehe VLA ist eine Art von alloca () richtig gemacht.

Natürlich ist eine lokale Struktur oder Array eine majorant des benötigten Raum verwendet, ist immer noch besser, und wenn Sie nicht so majorant Heapzuordnung mit Klar malloc () haben, ist wahrscheinlich vernünftig. Ich sehe keinen vernünftigen Gebrauch Fall, dass Sie wirklich, wirklich brauchen entweder alloca () oder VLA.

Viele interessante Antworten auf diese "alte" Frage, auch einige relativ neue Antworten, aber ich habe nicht gefunden, dass dies erwähnen....

Wenn verwendet, richtig und mit Sorgfalt, konsequente Nutzung von alloca() (vielleicht, Anwendung-weit) zu Griff kleine variable-Länge der Zuweisungen (oder auch C99 VLAs, wo verfügbar) kann dazu führen, insgesamt niedrigeren Stapel Wachstum als eines anderen gleichwertigen Umsetzung mit übergroßen lokale arrays fester Länge.So alloca() kann gut für Ihre stack wenn Sie verwenden Sie es sorgfältig.

Ich fand das Zitat in....OK, ich habe das Zitat oben.Aber wirklich, denke darüber nach....

@j_random_hacker ist sehr direkt in seinen Ausführungen unter anderen Antworten:Vermeiden Sie die Benutzung von alloca() zu Gunsten von übergroßen lokalen arrays nicht machen, Ihr Programm sicherer von stack-überlauf (es sei denn, Ihr compiler ist alt genug, um inlining von Funktionen, Verwendung alloca() in diesem Fall sollten Sie ein upgrade, oder es sei denn, Sie verwenden alloca() in Schleifen, in diesem Fall sollten Sie...nicht verwenden alloca() in Schleifen).

Ich habe gearbeitet, auf desktop - /server-Umgebungen und embedded-Systeme.Viele embedded-Systeme nicht mit einem Haufen an alle (Sie wissen nicht einmal, link in Unterstützung), für Gründe, die sind die Wahrnehmung, die dynamisch zugewiesenen Speicher ist böse wegen der Gefahr von memory leaks auf eine Anwendung, die nie Neustart seit Jahren in einer Zeit, die mehr vernünftige Begründung, dass der dynamische Speicher ist gefährlich, weil es kann nicht eindeutig festgestellt werden, dass eine Anwendung nie fragment seinen Haufen auf den Punkt der false memory Erschöpfung.Also embedded-Programmierer mit der linken sind ein paar alternativen.

alloca() (oder VLAs) möglicherweise genau das richtige Werkzeug für den job.

Ich habe gesehen, Zeit und Zeit wieder, wo ein Programmierer macht einen stack-allocated buffer "groß genug, um mit jeder möglichen Fall".In einer tief geschachtelten Aufruf-Baum, wiederholte Verwendung des (anti-?)Muster führt zu übertrieben stack verwenden.(Stellen Sie sich vor einem Aufruf Baum 20 Ebenen Tiefe, wo in jeder Ebene für verschiedene Gründe, die Funktion blind über-weist einen Puffer von 1024 bytes "nur um sicher zu sein", wenn es in der Regel nur 16 oder weniger von Ihnen, und nur in sehr seltenen Fällen auch mehr.) Eine alternative ist die Verwendung alloca() oder VLAs und reservieren Sie nur, wie viel stack-Speicher als Ihre Funktion benötigt, um nicht unnötig belasten den stack.Hoffentlich, wenn eine Funktion in der Aufruf-Baum braucht ein größer-als-normal-Zuordnung, andere in der call tree sind immer noch mit Ihrer normalen kleinen Zuordnungen, und den gesamten Anwendungs-stack-Nutzung ist deutlich weniger, als wenn jede Funktion blind überlastet einem lokalen Puffer.

Aber wenn Sie sich entscheiden zu verwenden alloca()...

Basierend auf anderen Antworten auf dieser Seite, es scheint, dass VLAs sicher sein sollten (die Sie nicht zusammengesetzte stack Zuweisungen, wenn innerhalb einer Schleife), aber wenn Sie alloca(), achten Sie darauf , nicht zu verwenden es innerhalb einer Schleife, und stellen Sie sicher Ihre Funktion lässt sich nicht inlined, ob es irgendeine chance es könnte aufgerufen werden, die innerhalb einer anderen Funktion-Schleife.

Hier ist der Grund:

char x;
char *y=malloc(1);
char *z=alloca(&x-y);
*z = 1;

Nicht, dass jemand würde diesen Code schreiben, aber die Größe Argument Sie vorbei fast alloca kommt sicherlich aus einer Art von Input, der böswillig Ihr Programm bekommen könnte darauf abzielen, etwas Großes wie das alloca. Nach allem, wenn die Größe nicht auf Eingabe basiert oder die Möglichkeit zu sein, nicht groß hat, warum erklären Sie haben nicht nur einen kleinen, feste Größe lokalen Puffer?

Praktisch alle Code alloca und / oder C99 vlas hat schwerwiegende Fehler, die zu Abstürzen führen wird (wenn man Glück hat) oder Privileg Kompromiss (wenn Sie nicht so Glück haben).

Ein Ort, wo alloca() ist besonders gefährlich, als malloc() ist der Kern - Kern einer typischen Betriebssystem hat eine feste Größe Stapelspeicher hart codiert in eines ihrer Header; es ist nicht so flexibel wie der Stapel von einer Anwendung. Tätigen eines Anrufs mit einer ungerechtfertigten Größe alloca() kann der Kernel zum Absturz bringen. Bestimmte Compiler warnen Nutzung von alloca() (und sogar VLAs für diese Angelegenheit) unter bestimmten Optionen, die eingeschaltet werden sollten, während einen Kernel-Code kompiliert - hier ist es besser, Speicher im Heap zu reservieren, die nicht durch eine hartcodierte Begrenzung festgelegt ist .

Wenn Sie versehentlich über den mit alloca (aufgrund eines Pufferüberlauf zum Beispiel) zugeordneten Block schreiben, dann überschreiben Sie die Absenderadresse Ihre Funktion, denn das ist eine befindet sich „oben“ auf der Stapel, dh nach Ihr zugeordneten Block.

Die Folge davon ist zweifach:

  1. Das Programm wird spektakulär abstürzen und es wird unmöglich sein, warum oder zu sagen, wo es abgestürzt ist (Stapel wird höchstwahrscheinlich aufgrund des überschriebenen Rahmenzeiger auf eine zufällige Adresse entspannen).

  2. Es macht Pufferüberlauf oft gefährlicher, da ein böswilliger Benutzer ein spezielles Nutzlasthandwerk kann, die auf dem Stapel gelegt werden würden, und kann daher ausgeführt enden.

Im Gegensatz dazu, wenn Sie über einen Block auf dem Heap schreiben Sie „nur“ Heapbeschädigung bekommen. Das Programm wird wahrscheinlich unerwartet beendet, aber den Stapel richtig entspannen, wodurch die Möglichkeit von bösartiger Code-Ausführung reduziert wird.

Ein pitfall mit alloca ist, dass longjmp spult es.

Das heißt, wenn Sie einen Zusammenhang mit setjmp speichern, dann etwas Speicher alloca, dann auf den Kontext longjmp, können Sie den alloca Speicher verlieren (ohne jede Art von Mitteilung). Der Stapelzeiger ist zurück, wo es war, und so ist der Speicher nicht mehr reserviert; Wenn Sie eine Funktion aufrufen oder eine andere alloca tun, werden Sie die ursprüngliche alloca clobber.

Um zu klären, was ich beziehe mich speziell auf hier ist eine Situation, in der longjmp nicht aus der Funktion zurückkehrt, wo der alloca stattfand! Vielmehr spart eine Funktion Zusammenhang mit setjmp; ordnet dann mit alloca Speicher und schließlich ein longjmp findet in diesem Kontext. Dass alloca Speicher-Funktion nicht alle befreit; nur all die Erinnerung, dass es seit dem setjmp zugeordnet. Natürlich, ich bin über ein beobachtetes Verhalten zu sprechen; Eine solche Vorschrift ist jeder alloca dokumentiert, die ich kenne.

Der Fokus in der Dokumentation ist in der Regel auf dem Konzept, dass Speicher alloca ist im Zusammenhang mit einer Funktion Aktivierung, nicht mit einem Block; dass mehrere Aufrufe von alloca greifen nur mehr Stapelspeicher, der alle freigegeben wird, wenn die Funktion beendet wird. Nicht so; der Speicher wird mit dem Verfahren Kontext tatsächlich verbunden ist. Wenn der Zusammenhang mit longjmp gestellt wird, so ist der Stand der alloca Zustand. Es ist eine Folge des Stapelzeigerregisters selbst für die Zuweisung verwendet wird, und auch (notwendigerweise) gespeichert und im jmp_buf gestellt.

Übrigens, dieses, wenn es auf diese Weise funktioniert, bietet einen plausiblen Mechanismus für bewusst Speicherfreigabe, die mit alloca zugeordnet wurde.

Ich habe in diesen als Ursache eines Fehlers ausgeführt werden.

Ich glaube nicht, dass jemand dies erwähnt hat: Die Verwendung von alloca in einer Funktion behindern oder einige Optimierungen deaktivieren, die sonst in der Funktion angewendet werden könnte, da der Compiler nicht die Größe des Stapelrahmen der Funktion kennen kann.

Zum Beispiel kann eine gemeinsame Optimierung von Compilern C Verwendung des Rahmen-Pointers in einer Funktion zu beseitigen, werden Rahmenzugriffe relativ zu dem Stapelzeiger statt gemacht; so gibt es ein weiteres Register für die allgemeinen Gebrauch. Aber wenn alloca innerhalb der Funktion aufgerufen wird, wird die Differenz zwischen SP und fp wird für einen Teil der Funktion unbekannt sein, so dass diese Optimierung kann nicht getan werden.

die Seltenheit ihrer Nutzung und seinen schattigen Status als Standardfunktion, Compiler-Designer möglicherweise deaktivieren Gegeben jeder Optimierung, die könnte Ursache Probleme mit alloca, wenn würde mehr als nur ein wenig Mühe, um es mit alloca zu arbeiten.

UPDATE: Da lokale Arrays variabler Länge zu C und C ++, und da diese derzeit sehr ähnlichen Code Generation Fragen an den Compiler als alloca hinzugefügt wurden, sehe ich, dass ‚Seltenheit Verwendung und schattigen Status‘ gilt nicht für den zugrunde liegenden Mechanismus; aber ich würde immer noch entweder, dass die Verwendung von alloca vermuten oder VLA neigt Codegenerierung innerhalb einer Funktion zu beeinträchtigen, die sie verwendet. Ich würde jedes Feedback von Compiler Designern begrüßen zu können.

Leider ist das wirklich genial alloca() aus der fast ehrfürchtigen tcc fehlt. Gcc tut alloca() haben.

  1. Es sät den Samen seiner eigenen Zerstörung. Mit Rück als destructor.

  2. Wie malloc() es einen ungültigen Zeiger auf nicht zurückgibt, die auf modernen Systemen mit einer MMU (und hoffentlich starten die ohne).

  3. segfault wird
  4. Im Gegensatz zu Auto Variablen Sie die Größe zur Laufzeit angeben.

Es funktioniert gut mit Rekursion. Sie können statische Variablen verwenden, etwas ähnliches zu Endrekursion zu erreichen und verwenden nur wenige andere Infos zu jeder Iteration übergeben.

Wenn Sie drücken zu tief Sie eines segfault versichert sind (wenn Sie eine MMU haben).

Beachten Sie, dass malloc() nicht mehr bietet, da es NULL zurückgibt (die auch, wenn zugewiesen wird segfault), wenn das System aus dem Speicher ist. D. h alles, was Sie tun können, ist Kaution oder einfach nur versuchen, es irgendeine Art und Weise zugeordnet werden.

Zur Nutzung malloc() ich Globals verwenden und ordnen sie NULL. Wenn der Zeiger nicht NULL ist ich frei, bevor ich malloc() verwenden.

Sie können auch realloc() als allgemeiner Fall verwenden, wenn alle vorhandenen Daten kopiert werden sollen. Sie müssen Zeiger überprüfen, bevor arbeiten, wenn Sie nach dem realloc() kopieren oder verketten wollen.

3.2.5.2 Vorteile von alloca

Prozesse nur eine begrenzte Menge an Stapelspeichern zur Verfügung haben -. Weit weniger als die Menge an Speichern zur Verfügung malloc()

Durch die Verwendung von alloca() Sie drastisch erhöhen Ihre Chancen, einen Stack-Überlauf-Fehler bekommen (wenn man Glück hat, oder ein unerklärlicher Absturz, wenn Sie nicht).

Nicht sehr hübsch, aber wenn die Leistung wirklich wichtig ist, könnten Sie etwas Platz auf dem Stack preallocate.

Wenn Sie bereits jetzt die maximale Größe des Speichers Ihren Bedarf sperren und Sie möchten Überlauf überprüft zu halten, können Sie etwas tun könnten, wie:

void f()
{
    char array_on_stack[ MAX_BYTES_TO_ALLOCATE ];
    SomeType *p = (SomeType *)array;

    (...)
}

Eigentlich ist alloca nicht garantiert den Stapel zu verwenden. Tatsächlich weist die gcc-2.95 Implementierung von alloca aus dem Heap-Speicher malloc selbst. Auch die Implementierung ist fehlerhaft, kann es zu einem Speicherverlust und zu einem unerwarteten Verhalten führen, wenn Sie es in einem Block mit einer weiteren Verwendung von GOTO. Nicht zu sagen, dass Sie es nie verwenden sollten, aber einige Male alloca führt zu mehr Aufwand als es releaves frome.

Die Funktion alloca ist groß und und alle Neinsager einfach verbreiten FUD.

void foo()
{
    int x = 50000; 
    char array[x];
    char *parray = (char *)alloca(x);
}

Array und pArray sind genau das gleiche mit genau den gleichen Risiken. Zu sagen, man ist besser als der andere ist eine syntaktische Wahl, kein technisches.

Wie bei Stack-Variablen vs Heap-Variablen wählen, gibt es eine Menge Vorteile zu langen laufenden Programmen Stapel über Haufen Lebensdauer für Variablen mit in-scope verwenden. Sie vermeiden Heap-Fragmentierung und man kann mit nicht genutzten (unbrauchbar) Heap-Speicher wächst Ihren Prozessraum vermeiden. Sie brauchen nicht, es zu bereinigen. Sie können die Stack-Zuweisung auf den Prozess steuern.

Warum ist das schlecht?

IMHO ist alloca schlechte Praxis betrachtet, weil jeder von anstrengend die Stapelgröße Grenze Angst hat.

Ich lernte viel von diesem Thread zu lesen und einige andere Verbindungen:

Ich benutze alloca hauptsächlich meine Ebene C-Dateien übersetzbar auf msvc und gcc ohne Änderung, C89-Stil zu machen, kein #ifdef _MSC_VER, etc.

Danke! Dieser Thread hat mich zu dieser Website anmelden:)

Meiner Meinung nach, alloca (), soweit verfügbar, sollte nur in einer eingeschränkten Weise verwendet werden. Ganz ähnlich wie die Verwendung von „goto“, eine recht große Anzahl von ansonsten vernünftigen Menschen hat eine starke Abneigung nicht nur auf die Verwendung, sondern auch die Existenz, alloca ().

Für Embedded Einsatz, wo die Stack-Größe bekannt ist und Grenzen können über Konvention und Analysen über die Größe der Zuordnung, und wo der Compiler aktualisiert werden kann nicht unterstützen C99 +, die Verwendung von alloca auferlegt werden () ist in Ordnung, und ich ‚es habe einmal zu verwenden.

Wenn verfügbar, VLAs kann einige Vorteile gegenüber alloca hat (): Der Compiler kann Stapel Limit Kontrollen erzeugen, die out-of-bounds Zugang zu fangen, wenn Array Stil Zugriff verwendet wird (ich weiß nicht, ob irgendwelche Compiler dies zu tun, aber es ist machbar) und Analyse des Codes kann bestimmen, ob die Array-Zugriffsausdrücke richtig begrenzt ist. Beachten Sie, dass in manchen Programmierumgebungen, wie Automobil, medizinische Geräte und Avionik, diese Analyse auch für feste Größe Arrays durchgeführt werden muss, sowohl automatisch (auf dem Stack) und statische Zuordnung (global oder lokal).

Auf Architekturen, die sowohl Daten speichern und Rücksprungadressen / Rahmenzeiger auf dem Stapel (von dem, was ich weiß, das ist alles von ihnen), jeder Stapel zugewiesene Variable kann gefährlich sein, weil die Adresse der Variablen genommen werden kann, und nicht markiert Eingang Werte könnten alle möglichen Unfug ermöglichen.

Portabilität ist weniger ein Problem in dem Raum eingebettet ist, aber es ist ein gutes Argument gegen die Verwendung von alloca () außerhalb von sorgfältig kontrollierten Bedingungen.

Außerhalb des Embedded-Bereichs, habe ich verwendet alloca () meist innerhalb Protokollierung und Formatierungsfunktionen für Effizienz, und in einem nicht-rekursive lexikalischen Scanner, in dem temporäre Struktur (zugewiesenes mit alloca () während tokenization und Klassifizierung geschaffen, dann ein persistentes Objekt (über malloc () zugewiesen), bevor die Funktion zurückkehrt aufgefüllt wird. die Verwendung von alloca () für die kleineren temporären Strukturen stark Fragmentierung reduziert, wenn das persistente Objekt zugeordnet ist.

Die meisten Antworten hier vermissen weitgehend den Punkt: es gibt einen Grund, warum _alloca() mit potentiell schlechter als nur große Objekte im Stapel zu speichern

.

Der Hauptunterschied zwischen dynamischem Speicher und _alloca() ist, dass die letztere leidet an einem zusätzlichen (schweren) Problem: Der zugeordnete Block ist nicht vom Compiler gesteuert , also gibt es keine Möglichkeit für den Compiler zu optimieren oder recyceln.

vergleichen:

while (condition) {
    char buffer[0x100]; // Chill.
    /* ... */
}

mit:

while (condition) {
    char* buffer = _alloca(0x100); // Bad!
    /* ... */
}

Das Problem mit dieser sollte klar sein.

Ich glaube nicht, dass irgendjemand dies erwähnt hat, aber alloca hat auch einige ernsthafte Sicherheitsprobleme nicht unbedingt mit malloc präsentieren (obwohl diese Themen auch mit beliebigen Stapel basierte Arrays, dynamisch oder nicht auftreten). Da der Speicher auf dem Stack zugeordnet ist, Pufferüberlauf / Unterschreitungen haben viel schlimmere Folgen als mit nur malloc.

Insbesondere die Absenderadresse für eine Funktion auf dem Stapel abgelegt. Wenn dieser Wert beschädigt wird, könnte Ihr Code in jedem ausführbaren Bereich des Speichers gehen gemacht werden. Compiler geht auf große Längen dies schwer zu machen (insbesondere nach Adressen Layout Randomisierung). Dies ist jedoch deutlich schlechter als nur ein Stack-Überlauf, da der beste Fall ist ein SEGFAULT, wenn der Rückgabewert beschädigt ist, aber es könnte auch beginnen ein zufälliges Stück Speicher ausgeführt wird oder im schlimmsten Fall einige Bereich des Speichers, die Ihr Programm die Sicherheit kompromittiert .

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top