6 Stimmen

Feststellen des Verhaltens von realloc() vor dessen Aufruf

So wie ich es verstanden habe, wird die Funktion realloc(), wenn sie aufgefordert wird, einen größeren Speicherblock zu reservieren, eine von drei verschiedenen Möglichkeiten nutzen:

if free contiguous block exists
    grow current block
else if sufficient memory
    allocate new memory
    copy old memory to new
    free old memory
else
    return null

Die Vergrößerung des aktuellen Blocks ist eine sehr billige Operation, also ist dies ein Verhalten, das ich gerne ausnutzen würde. Wenn ich jedoch Speicher neu zuweisen möchte, weil ich (zum Beispiel) ein Zeichen am Anfang einer bestehenden Zeichenkette einfügen möchte, möchte ich nicht, dass realloc() den Speicher kopiert. Am Ende kopiere ich die gesamte Zeichenkette mit realloc() und kopiere sie dann erneut manuell, um das erste Array-Element freizugeben.

Ist es möglich zu bestimmen, was realloc() tun wird? Wenn ja, ist es möglich, dies plattformübergreifend zu erreichen?

6voto

Rômulo Ceccon Punkte 9771

realloc() Das Verhalten des Programms hängt wahrscheinlich von seiner spezifischen Implementierung ab. Und Ihren Code darauf zu stützen, wäre ein schrecklicher Hack, der, gelinde gesagt, gegen die Kapselung verstößt.

Eine bessere Lösung für Ihr spezielles Beispiel wäre:

  1. Ermittlung der Größe des aktuellen Puffers
    • Weisen Sie einen neuen Puffer zu (mit malloc() ), größer als der vorherige
    • Kopieren Sie das gewünschte Präfix in den neuen Puffer
    • Kopieren der Zeichenkette aus dem vorherigen Puffer in den neuen Puffer, beginnend nach dem Präfix
    • Freigabe des vorherigen Puffers

2voto

Jonathan Leffler Punkte 694013

Wie in den Kommentaren angemerkt, ist der Fall 3 in der Frage (keine Erinnerung) falsch; realloc() gibt NULL zurück, wenn kein Speicherplatz verfügbar ist [Problem jetzt behoben].

Steve McConnell weist in 'Code Complete' darauf hin, dass, wenn Sie den Rückgabewert von realloc() in der einzigen Kopie des ursprünglichen Zeigers, wenn realloc() ausfällt, haben Sie gerade Speicherplatz verloren. Das heißt:

void *ptr = malloc(1024);
...
if ((ptr = realloc(ptr, 2048)) == 0)
{
    /* Oops - cannot free original memory allocation any more! */
}

Verschiedene Implementierungen von realloc() werden sich unterschiedlich verhalten. Das einzig Sichere, was man annehmen kann, ist, dass die Daten toujours verschoben werden - dass Sie immer eine neue Adresse erhalten, wenn Sie Speicher mit realloc() zuweisen.

Wie jemand anderes bereits sagte, sollten Sie Ihre Algorithmen überprüfen, wenn Sie sich darüber Sorgen machen.

1voto

Artelius Punkte 46771

Würde es helfen, die Zeichenfolge rückwärts zu speichern?

Ansonsten... malloc() einfach mehr Platz als nötig, und wenn der Platz ausgeht, kopieren Sie in einen neuen Puffer. Eine einfache Technik besteht darin, den Speicherplatz jedes Mal zu verdoppeln. Das funktioniert recht gut, denn je größer die Zeichenkette ist (d.h. je mehr Zeit das Kopieren in einen neuen Puffer in Anspruch nimmt), desto seltener muss dies geschehen.

Mit dieser Methode können Sie Ihre Zeichenkette im Puffer auch rechtsbündig ausrichten, so dass es einfach ist, Zeichen an den Anfang zu setzen.

0voto

Draemon Punkte 32703

Nein - und wenn Sie darüber nachdenken, kann das nicht funktionieren. In der Zeit, in der Sie prüfen, was er tun wird, und es tatsächlich tun, könnte ein anderer Prozess Speicher zuweisen. In einer Multithreading-Anwendung kann dies nicht funktionieren. In der Zeit zwischen der Überprüfung des Vorgangs und der tatsächlichen Ausführung könnte ein anderer Thread Speicher zuweisen.

Wenn Sie sich darüber Sorgen machen, ist es vielleicht an der Zeit, die von Ihnen verwendeten Datenstrukturen zu überprüfen, um zu sehen, ob Sie das Problem dort beheben können. Je nachdem, wie diese Zeichenketten aufgebaut sind, können Sie dies mit einem gut konzipierten Puffer recht effizient tun.

0voto

Ilya Punkte 3068

Ich glaube nicht, dass dies plattformübergreifend möglich ist. Hier ist der Code für die ulibc-Implementierung, die Ihnen einen Anhaltspunkt geben könnte, wie man es in plattformabhängiger Weise zu tun, eigentlich ist es besser, glibc Quelle zu finden, aber das war an der Spitze der Google-Suche :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X