C-Programmierung

malloc in c-Sprache

malloc in c-Sprache
Sie können aus zwei Gründen hierher kommen: Entweder Sie möchten Inhalte dynamisch zuweisen oder Sie möchten mehr über die Funktionsweise von malloc erfahren. In jedem Fall bist du hier richtig! Die dynamische Zuweisung ist ein Prozess, der viel passiert, aber im Allgemeinen verwenden wir ihn nicht selbst: Die überwiegende Mehrheit der Programmiersprachen verwaltet den Speicher für Sie, da dies eine harte Arbeit ist und wenn Sie es nicht richtig machen, hat dies Auswirkungen auf die Sicherheit.

Wenn Sie jedoch C-, C++- oder Assemblercode erstellen oder ein neues externes Modul in Ihrer bevorzugten Programmiersprache implementieren, müssen Sie Ihre dynamische Speicherzuweisung selbst verwalten.

Was ist dynamische Zuordnung?? Warum brauche ich malloc?

Nun, in allen Anwendungen, wenn Sie eine neue Variable erstellen - es wird oft als Variablendeklaration bezeichnet - du brauchst speicher um es zu speichern. Da Ihr Computer in der heutigen Zeit mehr als eine Anwendung gleichzeitig ausführen kann, sollte jede Anwendung Ihrem Betriebssystem Bescheid geben (hier Linux) dass es so viel Speicher braucht. Wenn Sie diese Art von Code schreiben:

#einschließen
#einschließen
#define DISK_SPACE_ARRAY_LENGTH 7
void getFreeDiskSpace(int statsList[], size_t listLength)
Rückkehr;

int main()
/* Enthält den freien Speicherplatz der letzten 7 Tage. */
int freeDiskSpace[DISK_SPACE_ARRAY_LENGTH] = 0;
getFreeDiskSpace(freeDiskSpace, DISK_SPACE_ARRAY_LENGTH);
EXIT_SUCCESS zurückgeben;

Das freeDiskSpace-Array benötigt Speicher, daher müssen Sie Linux um Genehmigung bitten, um etwas Speicher zu erhalten. Da beim Lesen des Quellcodes jedoch offensichtlich ist, dass Sie ein Array von 7 int benötigen, fragt der Compiler Linux automatisch danach und weist es auf dem Stack zu. Dies bedeutet im Grunde, dass dieser Speicher zerstört wird, wenn Sie die Funktion zurückgeben, in der die Variable deklariert ist. Deshalb können Sie das nicht:

#einschließen
#einschließen
#define DISK_SPACE_ARRAY_LENGTH 7
int* getFreeDiskSpace()
int statsList[DISK_SPACE_ARRAY_LENGTH] = 0;
/* WARUM MACHEN WIR DAS?! statsList wird ZERSTÖRT! */
Statistikliste zurückgeben;

int main()
/* Enthält den freien Speicherplatz der letzten 7 Tage. */
int *freeDiskSpace = NULL;
freeDiskSpace = getFreeDiskSpace();
EXIT_SUCCESS zurückgeben;

Du siehst das Problem jetzt leichter? Dann möchten Sie zwei Strings verketten. In Python und JavaScript würden Sie Folgendes tun:

newStr = str1 + str2

Aber in C funktioniert das ja bekanntlich nicht. Um zum Beispiel eine URL zu erstellen, müssen Sie zwei Strings verketten, z. B. URL-Pfad und Domänenname. In C haben wir strcat, richtig, aber es funktioniert nur, wenn Sie ein Array mit genügend Platz dafür haben.

Sie werden versucht sein, die Länge der neuen Zeichenfolge mit strlen zu ermitteln, und Sie haben Recht. Aber wie würden Sie Linux bitten, diese unbekannte Speichermenge zu reservieren?? Compiler kann Ihnen nicht helfen: Der genaue Speicherplatz, den Sie zuweisen möchten, ist nur zur Laufzeit bekannt. Genau hier brauchen Sie die dynamische Zuordnung und malloc.

Schreiben meiner ersten C-Funktion mit malloc

Bevor Sie Code schreiben, eine kleine Erklärung: malloc ermöglicht es Ihnen, eine bestimmte Anzahl von Bytes für Ihre Anwendungsnutzung zuzuweisen. Es ist wirklich einfach zu bedienen: Sie rufen malloc mit der Anzahl von Bytes auf, die Sie benötigen, und es gibt einen Zeiger auf Ihren neuen Bereich zurück, den Linux für Sie reserviert hat.

Sie haben nur 3 Aufgaben:

  1. Überprüfen Sie, ob malloc NULL zurückgibt. Das passiert, wenn Linux nicht genug Arbeitsspeicher hat, um ihn bereitzustellen.
  2. Geben Sie Ihre Variablen frei, sobald sie nicht verwendet wurden. Andernfalls verschwenden Sie Speicher und es wird Ihre Anwendung verlangsamen.
  3. Verwenden Sie niemals den Speicherbereich, nachdem Sie die Variable freigegeben haben.

Wenn Sie all diese Regeln befolgen, wird alles gut gehen und die dynamische Zuweisung wird Ihnen viele Probleme lösen. Da Sie wählen, wann Sie den Speicher freigeben, können Sie auch eine mit malloc zugewiesene Variable sicher zurückgeben. Vergiss nur nicht, es freizugeben!

Wenn Sie sich fragen, wie Sie eine Variable freigeben können, ist dies mit der kostenlosen Funktion. Rufen Sie es mit demselben Zeiger auf, den malloc Ihnen zurückgegeben hat, und der Speicher wird freigegeben free.

Lassen Sie mich es Ihnen mit dem Concat-Beispiel zeigen:

#einschließen
#einschließen
#einschließen
/*
* Vergessen Sie beim Aufrufen dieser Funktion nicht zu überprüfen, ob der Rückgabewert NULL ist
* Wenn es nicht NULL ist, müssen Sie den zurückgegebenen Zeiger free aufrufen, sobald der Wert
* wird nicht mehr verwendet.
*/
char* getUrl(const char* const baseUrl, const char* const toolPath)
size_t finalUrlLen = 0;
char* finalUrl = NULL;
/* Sicherheitscheck. */
if (baseUrl == NULL || toolPath == NULL)
NULL zurückgeben;

finalUrlLen = strlen(baseUrl) + strlen(toolPath);
/* '\0' nicht vergessen, daher die +1. */
finalUrl = malloc(sizeof(char) * (finalUrlLen + 1));
/* Malloc-Regeln befolgen… */
if (finalUrl == NULL)
NULL zurückgeben;

strcpy(finalUrl, baseUrl);
strcat(finalUrl, toolPath);
finalUrl zurückgeben;

int main()
char* googleImages = NULL;
googleImages = getUrl("https://www.Google.com", "/imghp");
if (googleImages == NULL)
EXIT_FAILURE zurückgeben;

puts("Tool-URL:");
puts(googleImages);
/* Es wird nicht mehr benötigt, befreie es. */
kostenlos(googleImages);
googleImages = NULL;
EXIT_SUCCESS zurückgeben;

Sie sehen also ein praktisches Beispiel für die Verwendung dynamischer Zuweisungen. Erstens vermeide ich Fallstricke wie das Geben des getUrl-Rückgabewerts direkt an die puts-Funktion. Dann nehme ich mir auch die Zeit zu kommentieren und zu dokumentieren, dass der Rückgabewert richtig freigegeben werden soll. Ich überprüfe auch überall auf NULL-Werte, damit alles Unerwartete sicher abgefangen werden kann, anstatt die Anwendung zum Absturz zu bringen.

Schließlich kümmere ich mich besonders darum, die Variable freizugeben und dann den Zeiger auf NULL zu setzen. So kommt man nicht in Versuchung - auch aus Versehen - den jetzt frei gewordenen Speicherbereich zu nutzen. Aber wie Sie sehen, ist es einfach, eine Variable freizugeben.

Sie werden vielleicht bemerken, dass ich sizeof in malloc . verwendet habe. Es ermöglicht zu wissen, wie viele Bytes ein Zeichen verwendet, und verdeutlicht die Absicht im Code, damit er besser lesbar ist. Für char ist sizeof(char) immer gleich 1, aber wenn Sie stattdessen ein Array von int verwenden, funktioniert es genauso. Wenn Sie beispielsweise 45 int reservieren müssen, tun Sie einfach:

fileSizeList = malloc(sizeof(int) * 45);

Auf diese Weise sehen Sie schnell, wie viel Sie zuweisen möchten, deshalb empfehle ich immer die Verwendung.

So funktioniert malloc unter der Haube?

malloc und free sind tatsächlich in allen C-Programmen enthaltene Funktionen, die in Ihrem Namen mit Linux kommunizieren talk. Es erleichtert auch die dynamische Zuweisung, da Linux beim Start nicht die Zuweisung von Variablen aller Größen zulässt.

Linux bietet zwei Möglichkeiten, um mehr Speicher zu erhalten: sbrk und mmap. Beide haben Einschränkungen, und eine davon ist: Sie können nur relativ große Mengen zuweisen, z. B. 4.096 Byte oder 8.192 Byte. Sie können nicht wie im Beispiel 50 Byte anfordern, aber Sie können auch keine 5.894 Byte anfordern.

Dies hat eine Erklärung: Linux muss eine Tabelle führen, in der angegeben ist, welche Anwendung welche Speicherzone reserviert hat. Und diese Tabelle verbraucht auch Speicherplatz. Wenn also jedes Byte eine neue Zeile in dieser Tabelle benötigt, wäre ein großer Teil des Speichers erforderlich. Aus diesem Grund ist der Speicher in große Blöcke von zum Beispiel 4.096 Bytes aufgeteilt, und so wie man in einem Lebensmittelgeschäft nicht zweieinhalb Orangen kaufen kann, kann man auch keine halben Blöcke verlangen.

Also nimmt malloc diese großen Blöcke und gibt dir ein kleines Stück dieser Speicherblöcke, wenn du es aufrufst. Wenn Sie nur wenige Variablen freigegeben haben, aber nicht genug, um die Freigabe eines ganzen Blocks zu rechtfertigen, kann das malloc-System Blöcke behalten und Speicherzonen recyceln, wenn Sie malloc erneut aufrufen. Dies hat den Vorteil, dass malloc schneller wird, jedoch kann der von malloc reservierte Speicher in keiner anderen Anwendung verwendet werden, während das Programm ihn derzeit nicht in der Realität verwendet.

Aber malloc ist schlau: Wenn Sie malloc aufrufen, um 16 MiB oder eine große Menge zuzuweisen, wird malloc Linux wahrscheinlich nach vollständigen Blöcken fragen, die nur für diese große Variable dediziert sind, indem es mmap verwendet. Auf diese Weise können Sie, wenn Sie kostenlos anrufen, diese Platzverschwendung eher vermeiden. Keine Sorge, malloc macht beim Recycling einen viel besseren Job als Menschen mit unserem Müll!

Fazit

Ich denke, jetzt verstehst du besser, wie das alles funktioniert. Natürlich ist die dynamische Zuweisung ein großes Thema und ich denke, wir können ein vollständiges Buch zu diesem Thema schreiben, aber dieser Artikel sollte Sie mit dem Konzept sowohl im Allgemeinen als auch mit praktischen Programmierhinweisen vertraut machen.

So verwenden Sie AutoKey zur Automatisierung von Linux-Spielen
AutoKey ist ein Desktop-Automatisierungsdienstprogramm für Linux und X11, programmiert in Python 3, GTK und Qt. Mithilfe der Skript- und MACRO-Funktio...
So zeigen Sie den FPS-Zähler in Linux-Spielen an
Linux-Gaming bekam einen großen Schub, als Valve 2012 die Linux-Unterstützung für den Steam-Client und seine Spiele ankündigte. Seitdem haben viele AA...
Herunterladen und Spielen von Sid Meier's Civilization VI unter Linux and
Einführung in das Spiel Civilization 6 ist eine moderne Version des klassischen Konzepts, das in der Reihe der Age of Empires-Spiele eingeführt wurde....