Frage

int main()
{
   char myString = NULL;
   realloc(&myString, 5);
   strncpy((char *)&myString, "test", 5);
}

Es scheint gut zu funktionieren, aber ich bin immer noch ein wenig verwirrt über Stack vs Heap. Ist das erlaubt? Wenn es erlaubt ist, tut myString manuell werden müssen befreit oder wird sie freigegeben werden, wenn es aus dem Geltungsbereich?


Edit: Danke für die Antworten, so dass ich nehme an, dies ebenso illegal ist

//I want the code to change myString to "tests"
char myString[5] = "test";
realloc(&myString, strlen(myString)+2);
myString[4] = 's';
myString[5] = '\0';
War es hilfreich?

Lösung

Nein, das ist völlig falsch. realloc sollte nur verwendet werden, um Speicher von malloc neu zuzuteilen, was Sie funktioniert nur durch Zufall tun, und schließlich abstürzen schrecklich

char *myString = malloc(x);
myString = realloc(myString,y);
free(myString)

Sie sind besser mit neuen und löschen, und noch besser aus std :: string verwenden, jedoch.

Andere Tipps

Einige Probleme mit dem Code, den Sie geschrieben:

  • Ja, Sie alles, was Sie mit malloc zuteilen befreien müssen, und realloc und die anderen zugehörigen Funktionen Speicherzuweisung C-Stil.
  • Ich glaube, Sie char * myString haben soll, nicht char. Vorbei an der Adresse von etwas auf dem Stapel (Char) ist völlig falsch.
  • Sie benötigen myString char Zeiger auf NULL zu initialisieren, bevor es in realloc verwenden.
  • Sie sollten 4 in Strncpy werden nicht vorbei 5, wenn Sie eine größere Zeichenfolge musste man Speicher überschreiben würde.
  • Sie sollten den Puffer Sie in Ihrem Beispiel
  • erstellt werden zu befreien
  • Sie sollten den Rückgabewert Ihrer realloc Anruf checken. realloc ()
  

[In Bezug auf realloc Rückgabewert:] Nach dem erfolgreichen Abschluss mit einer Größe   nicht gleich 0 ist, realloc () gibt einen   Zeiger auf die (ggf. verschoben)   zugewiesenen Platz. Wenn Größe 0, entweder   ein Null-Zeiger oder ein einzigartiger Zeiger   das kann erfolgreich werden weitergegeben   free () zurückgegeben. Wenn es nicht   genug, um die verfügbare Speicher, realloc ()   gibt einen Null-Zeiger und setzt errno   auf [ENOMEM].

  • re-alloc wird wie malloc funktionieren, wenn Sie in NULL übergeben:
  

Wenn ptr ein Nullzeiger ist, realloc ()   verhält sich wie malloc () für die   angegebene Größe.

Eine C ++ Art und Weise, es zu tun:

Sie markiert diese als C ++ aber, und es ist mehr typsicher C ++ 's neuer Betreiber zu verwenden. Obwohl der neue Betreiber für Umschichtungen nicht zulässt, wird es für die Zuweisungen arbeiten und für die Wiederverwendung von vorhandenen Puffer (Platzierung neu).

char *myString = new char[5];
strncpy(myString, "test", 4); 
//...
delete[] myString;

oder auch:

#include <string>

//...

std::string str = "test";

Quelle der Top-2-Quotes

Dies sollte nicht funktionieren. Du reallocing etwas, das nicht in erster Linie malloced wurde. Und nein, es wird nicht befreit, wenn sie aus dem Geltungsbereich -., Wenn Sie malloc oder realloc verwenden, es ist alles an Ihnen

Update: Ihre Änderung ändert nichts - du bist immer noch versuchen, etwas realloc, die nicht in erster Linie malloced wurde. Sie können aber auch nicht den Rückgabewert von realloc ignorieren - wenn realloc den Speicher woanders zu bewegen hat, werden Sie, dass in der Rück finden. Mit anderen Worten:

char* ptr = malloc(4);
ptr = realloc(ptr, 5);

Nach realloc, ptr zu einem ganz anderen Ort im Speicher zeigen könnte, und weiterhin den ursprünglichen Wert auf die Verwendung von ptr Sie Speicher verwenden lassen könnte, die freigegeben worden ist und das ist nicht so groß, wie Sie denken, es ist.

Das ist gefährlich! Dies wird beschädigt Ihren Stack. Wenn Sie etwas auf dem Stapel einer Funktion realloc waren, die dann zur Haupt () zurückgegeben, würden Sie tatsächlich den Stack-Frame am Ende überschreiben und an einer anderen Stelle als Haupt Rückkehr (). Das stellt ein mögliches Sicherheitsloch.

Versuchen Sie, die folgenden ausgeführt wird. Wenn es auf realloc abstürzt, haben Sie Glück. Sie können mit so etwas wie memcpy ernsthaften Schaden anrichten (& myString).

int dostuff();

int main()
{
        dostuff();
        return 0;
}

int dostuff()
{
        char myString = NULL;
        realloc(&myString, 5);
        strncpy((char *)&myString, "test", 5);
        return 0;
}

Dies ist, was Sie nie tun sollten. Der Versuch, zu befreien () oder realloc () eine Stapelvariable zu undefiniertem Verhalten einschließlich (aber nicht beschränkt auf) beschädigt Stapel (was zu unvorhersagbaren Ablaufsteuerung), beschädigte Heap-Service-Strukturen, beschädigte Anwenderspeicher führen kann. Sie haben Glück, wenn das Programm nur mit einem AV-abstürzt. Es kann in einigen Fällen funktionieren, aber man sollte nie so zu tun versuchen.

Als Faustregel gilt: nur Speicher auf die Speichermanager zurückkehren wurde zugeteilt auf. In diesem Fall versuchen Sie nicht, den Stack-Variable auf den Laufzeit-Heap zurückzukehren.

Ihr Programm ist syntaktisch gültig C ++, aber es wird nicht definiertes Verhalten produzieren, weil Sie die Adresse eines Stapels Objekt auf den Heap allocator passieren. Normalerweise bedeutet dies, dass Ihr Programm bei seiner Ausführung zum Absturz bringen.

Der Stapel und Haufen sind zwei verschiedene Bereiche des Speichers zu dem Prozess zugeordnet Ihr Programm ausgeführt wird. Der Stapel wächst, wie Sie eine Funktion eingeben ihre Argumente und lokale Variablen zu halten, und es schrumpft automatisch, wie Sie aus der Funktion zurück. Der Haufen, auf der anderen Seite, ist ein separater Adressbereich, in dem Speicher nach Bedarf erhalten werden kann und muss explizit freigegeben werden, wenn es nicht mehr benötigt wird.

Wenn die Adresse einer lokalen Variablen übergeben wird an realloc (), kann es versuchen, seinen Speicher zu befreien und es an anderer Stelle zuzuweisen. Da die Adresse nicht aus dem Heap ist, und realloc () auf dem Heap arbeitet, wird dies nicht gelingen. Wahrscheinlich realloc () wird die Adresse zu erkennen ist nicht aus dem Heap und das Programm abbrechen.


Abgesehen davon, das Beispielprogramm enthält einige logischen Fehler.


char myString = NULL;

Sie deklarieren eine Variable ein Zeichen zu halten, kein String. Ein C-String besitzt Typ char*, das heißt ein Zeiger verkohlen.

Auch ist der char zugewiesen NULL, die Adresse Null, die üblicherweise auf ungültige Zeiger zugeordnet ist. Dies kompiliert, da der Präprozessor durch die wörtliche NULL 0 ersetzt. Wirklich, Sie speichern einen Null-Byte in dem char, das heißt, auch durch Konvention, der Terminator eines C-String.


realloc(&myString, 5);

Wie bereits erwähnt, ist dies illegal, weil Sie die Adresse eines Stapels Objekt auf den Heap allocator passieren. Dieses Problem bleibt in Ihrem zweiten Codebeispiel.

Auch Sie verwerfen den Rückgabewert. realloc() gibt die Adresse, wo der neue Speicher zugewiesen wurde. Es kann nicht die gleiche Adresse wie zuvor. Es kann sogar NULL sein, das ist realloc() Weg Ihnen zu sagen, dass die Speicherkapazität erschöpft ging.


strncpy((char *)&myString, "test", 5);

Das ist richtig, aber die Besetzung ist überflüssig.


Hier ist eine korrekte Version des Programms:


#include <stdlib.h>
#include <string.h>

int main()
{
   /* allocate space for, say, one character + terminator */
   char* myString = (char*) malloc(2);

   /* some code using myString omitted */

   /* get more space */
   myString = (char*) realloc(myString, 5);

   /* write to the string */
   strncpy(myString, "test", 5);

   /* free the memory */
   free(myString);

   return 0;
}

In C ++ ist es besser, realloc () ganz zu vermeiden. Zum Beispiel könnten Sie so etwas wie die folgenden verwenden:


#include <string>

int main()
{
   std::string myString;

   /* some code using myString */

   myString = "test";

   return 0;
}

Sie haben nicht frei myString, da es auf dem Stapel befindet (das wird „befreit“, wenn Umfang zu verlassen).

realloc ist hier illegal, die Adresse NULL werden muss oder eine Adresse, die durch einen früheren Aufruf zurückgegeben realloc, malloc oder calloc.

Jede Variable erklären Sie ist auf dem Stapel, auch ein Zeiger:

int * x;

Die Variable x ist auf dem Stack! Es ist vom Typ pointer und hält eine Adresse.

x = (int *) malloc (sizeof (int));

weist die Adresse von malloc der Variablen x zurück! Der Gehalt an x ist eine Speicheradresse!

Das Problem mit dem, was Sie tun, ist, dass Sie mit etwas sind Ausmisten, die nicht eine Variable ist. Sie definiert myString als Zeichen, und versuchen daher ihre Adresse zu ändern. Das ist schlecht.

Die Funktion realloc () soll nichts hineingeben ändern. Es dauert einen Zeiger zu einem gewissen Speicher auf dem Heap (oder den Null-Zeiger, wenn nichts bereits vergeben) und gibt einen Zeiger zu einem gewissen Speicher auf dem Heap.

Daher stellen Sie entweder einen Null-Zeiger oder einen Zeiger auf etwas von malloc () oder realloc () oder calloc () und speichern die Zeiger zurückgegeben.

So etwas wie

char * myString = NULL;
myString = realloc(myString, 5);

wird funktionieren, aber Sie wollen befreien () myString.

In C ++ verwendet jedoch std :: string.

Als Antwort auf Ihr zweites Codebeispiel:

Ja, das ist auch illegal. myString nicht mit malloc (oder calloc), so kann es nicht mit realloc neu zugewiesen werden, oder mit freiem befreit.

Plus, dass realloc keinen Zeiger auf einen Zeiger als erstes Argument nimmt. Es nimmt einen Zeiger auf zugewiesenen Speicher und gibt ein anderes (möglicherweise unterschiedliche) Zeiger. Schreiben Sie den Aufruf wie folgt statt:

myString = realloc(myString, strlen(myString)+2);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top