Wie verhindern Sie Arrays variabler Länge vor einem Absturz, wenn nicht genügend Speicher ist?

StackOverflow https://stackoverflow.com/questions/4151172

  •  08-10-2019
  •  | 
  •  

Frage

Vor Arrays variabler Länge unterstützt, würde ich sie dynamisch zuweisen wie folgt aus:

int foo(size_t n)
{
    int *arr = malloc(n * sizeof int);
    if (!arr) return ENOMEM; /* not enough memory */
    .
    . else do stuff with arr[]
    .
    free(arr);
    return 0;
}

Mit Arrays variabler Länge kann ich es jetzt saubere aussehen:

int bar(size_t n)
{
    int arr[n];
    .
    . do stuff with arr[]
    .
    return 0;
}

Aber ich habe jetzt nicht "out of memory" zu überprüfen. In der Tat, stürzt das Programm, wenn n zu groß ist.

Wie kann ich anmutig von bar (n) bürgen, wenn n zu groß ist?

War es hilfreich?

Lösung

Die Situation ist genau das unverändert von allen anderen lokalen Variablen - eine Erklärung wie folgt aus:

int baz(void)
{
    int arr[100000];
    .
    . do stuff with arr[]
    .
    return 0;
}

hat genau das gleiche Problem. Die „Lösung“ ist das gleiche wie es immer gewesen ist - nicht recurse zu tief, und weist keine sehr große Datenstrukturen mit automatischer Speicherdauer (weiterhin Verwendung malloc() für diese Fälle). Der Wert von „sehr großen“ hängt stark von Ihrer Umgebung.

Mit anderen Worten, nicht ausdrücklich erklären, int array[n]; es sei denn Sie wissen, dass n auf einen vernünftigen Wert begrenzt ist, so dass Sie wäre glücklich gewesen, eine Reihe von dieser maximalen Größe als ein gewöhnlichen, nicht variabel modifizierten Typ Array zu deklarieren .

(Ja, das bedeutet, dass Typ-Arrays variabel modifiziert sind nicht so nützlich, wie sie zunächst erscheinen, da man sehr wenig gewinnen Sie einfach über den Array deklariert bei der maximal benötigten Größe).

Andere Tipps

Sie können verhindern, dass sie vor einem Absturz durch nicht mit ihnen. :)

In alle Ernst, gibt es fast keine sichere Art und Weise zu verwenden Arrays variabler Länge Ihr Leben leichter zu machen, wenn Sie von der Größe starke Grenzen haben. Auf der anderen Seite, können Sie sie bedingt nutzen, in einer Weise, wie folgt aus:

char vla_buf[n < 1000 ? n : 1];
char *buf = sizeof vla_buf < n ? malloc(n) : vla_buf;
if (!buf) goto error;
/* ... Do stuff with buf ... */
if (buf != vla_buf) free(buf);

Während das sieht aus wie nutzlos Schmerzen, kann es einen großen Unterschied in der Leistung, vor allem in Threaded-Anwendungen, wo viele Anrufe malloc und free in Sperr-Konflikt führen könnten. (Ein bemerkenswerter Nebeneffekt dieses Tricks ist, dass Sie durch einfaches Austauschen [n < 1000 ? n : 1] mit 1000 alten Compiler ohne VLAs unterstützen können, beispielsweise mit einem Makro.)

Ein weiterer obskuren Fall, in dem VLAs nützlich sein kann, ist in rekursiven Algorithmen, wo Sie die Gesamtzahl der Array-Einträge wissen über alle Ebenen der Rekursion erforderlich durch n begrenzt ist, wo n klein genug ist, Sie sind davon überzeugt, es nicht überläuft die Stapel, aber wo es zu n Ebenen der Rekursion und individueller Ebene sein könnte, die n Elemente aufbrauchen. Vor der C99, der einzige Weg, um diesen Fall zu behandeln, ohne n^2 Stapelspeicher zu nehmen war malloc zu verwenden. Mit VLAs, können Sie das Problem vollständig auf dem Stapel lösen.

Beachten Sie, diese Fälle, in denen VLAs wirklich von Vorteil sind, sind verdammt selten. Normalerweise VLA ist nur eine Möglichkeit, sich zu täuschen, dass die Speicherverwaltung ist einfach, bis Sie etwas erhalten, indem die daraus resultierenden (trivial-to-Exploit) Verwundbarkeiten Sie erstellt haben. : -)

Edit: Um eine bessere ursprüngliche Frage Adresse OP:

#define MAX_VLA 10000
int bar(size_t n)
{
    int arr[n <= MAX_VLA ? n : 1];
    if (sizeof arr/sizeof *arr < n) return ENOMEM;
    /* ... */
    return 0;
}

In Wirklichkeit ist es unerschwinglich teuer überall aus Speicherbedingungen zu überprüfen. Die enterprisy Art und Weise mit massiven Daten umzugehen ist, zu begrenzen Datengrößen durch harte Kappe auf Größe an einzelnem frühem Kontrollpunkt definieren und schnell und elegant ausfallen, wenn die Kappe Hit ist.

Was ich nur vorgeschlagen, einfach und dumm. Aber sein, was jedes normale (nicht-wissenschaftliches oder spezielles) Produkt immer tut. Und das, was normalerweise durch die Kunden erwartet.

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