Entwickler-Ecke
Alle Sprachen - Alle Plattformen - malloc Funktion
tomycat - Di 22.08.17 10:30
Titel: malloc Funktion
hallo,
die malloc Funktion ist eine tolle Funktion :-)
Zu meinem problem, ich habe mehrere Beispiel gefunden, aber so richtig klar ist es mir nicht.
Mit malloc resaviert man Speicher und free gibt man ihn wieder frei. Aber ich habe nicht Beispiel gesehen wie, das passiert, wenn man nicht malloc/free verwendet.
Moderiert von Th69: Topic aus Andere .NET-Sprachen verschoben am Di 22.08.2017 um 13:12
Delete - Di 22.08.17 12:01
- Nachträglich durch die Entwickler-Ecke gelöscht -
tomycat - Di 22.08.17 12:13
sorry, es handelt sich um die Sprache C. Richtung php Erweiterung.
Delete - Di 22.08.17 12:36
- Nachträglich durch die Entwickler-Ecke gelöscht -
tomycat - Mi 23.08.17 11:21
Es ist alles richtig, was du geschrieben hast :-)
Ich stelle jetzt meine Frage mal anderst.
Laut Buch steht drin, man muss bei Motoradfahren einen Helm tragen, sonsten bekommet man ärger mit der Polizei. Dann gibt es blaue grüne und rote Motoradhelme...
Alles recht und schön. Meine Frage ist: Wann genau ist der Helm wichtig? Es kommt zum Unfall, was passiert dann alles, was könnte passieren?
Ralf Jansen - Mi 23.08.17 12:36
Zitat: |
Es kommt zum Unfall, was passiert dann alles, was könnte passieren? |
Wenn du Methoden zum Speicher allozieren falsch benutzt komt es zu Speicher Problemen :gruebel: Also primär Speicherlecks bis dein Speicher aus ist und dein Programm abschmiert.
Du scheinst eine spezielle Antwort zu wünschen aber das geht bei einer so allgemeinen Frage eher nicht.
Delete - Mi 23.08.17 12:46
- Nachträglich durch die Entwickler-Ecke gelöscht -
Ralf Jansen - Mi 23.08.17 14:44
Zitat: |
meine ausstehende Parkplatz-Metapher ruiniert. :crying: |
Mich würde die Story interessieren.
Delete - Mi 23.08.17 14:56
- Nachträglich durch die Entwickler-Ecke gelöscht -
hydemarie - Mi 23.08.17 18:09
Frühlingsrolle hat folgendes geschrieben : |
malloc() und free() haben in der Sprache C ihre Berechtigung. Mit C++ kam das new hinzu, was genauso viel bewirkt wie malloc(). |
Das ist natürlich
Unsinn nicht ganz richtig, denn
new alloziiert keinen
definierten Speicher, sondern erzeugt eine neue Instanz einer Klasse (inkl. Konstruktoraufruf, sofern vorhanden).
malloc() schiebt erst mal einen bestimmten
Speicherbereich frei, den du dann mit irgendwas - nicht zwangsläufig mit einer Klasseninstanz, sondern z.B. auch mit einem
char* - vollschreiben kannst. Das geht auch in C++ noch. ;)
Delete - Mi 23.08.17 19:08
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69 - Mi 23.08.17 19:38
Sorry Frühlingsrolle, aber dein Code ist falsch (UB).
hydemarie - Mi 23.08.17 19:41
Und zu umständlich. Wenn sizeof(char) jemals nicht 1 sein sollte, ist dein Compiler mit absoluter Sicherheit kaputt.
tomycat - Do 24.08.17 07:41
ok danke Jungs,
kann man jemand ein Beispiel machen, wo man sagt HIER braucht man malloc und so stützt das Prog ab.
hydemarie - Do 24.08.17 09:27
Du
brauchst malloc/
calloc beziehungsweise
realloc zum Beispiel für C und damit auch die Interaktion mit C.
Konkreter Anwendungsfall: du möchtest eine Textdatei zeilenweise in eine Variable speichern. Da C keine
std::strings und keine Vektoren kennt, bräuchtest du dafür zum Beispiel einen
char**-Pointer. Die einzelnen Strings brauchen aber jedes Mal eine andere Anzahl an Byte, sie sind ja selten identisch.
C++-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| while (textfile) { char* next_line = strchr(textfile, '\n'); int linelength = next_line ? (next_line - textfile) : strlen(textfile); char* temp_str = (char *)malloc(linelength + 1);
if (temp_str) { memcpy(temp_str, textfile, linelength); temp_str[linelength] = '\0'; free(temp_str); }
textfile = next_line ? (next_line + 1) : NULL; } |
Absturz (Beispiel): Räume einen Speicherbereich frei, der dir nicht gehört.
C++-Quelltext
1: 2:
| int quux = 42; free(quux); |
Delete - Do 24.08.17 09:48
- Nachträglich durch die Entwickler-Ecke gelöscht -
hydemarie - Do 24.08.17 09:53
Es ergibt nicht viel Sinn, hier einen Pointer zu verwenden. Aber warum sollte der Code falsch sein?
Nachtrag: Warum printf?
Delete - Do 24.08.17 10:07
- Nachträglich durch die Entwickler-Ecke gelöscht -
hydemarie - Do 24.08.17 10:12
Nö, ich meinte das Beispiel aus Wikibooks.
Delete - Do 24.08.17 10:20
- Nachträglich durch die Entwickler-Ecke gelöscht -
Th69 - Do 24.08.17 11:14
OK, ich dachte, das sei offensichtlich. ;-)
Ich kommentiere ihn deshalb mal:
C++-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| char* cNeu = new char[3]; cNeu = "Neu"; printf("%s", cNeu); delete(cNeu); char* cAlt = (char*)malloc(3 * sizeof(char)); cAlt = "Alt"; printf("%s", cAlt); free(cAlt); |
Wahrscheinlich meintest du in Zeile 2 (und [jetzt] 10):
C++-Quelltext
1: 2: 3:
| strncpy(cNeu, "Neu", 3); strncpy(cAlt, "Alt", 3); |
d.h. du schreibst in den mittels
new/
malloc allozierten Speicherbereich etwas rein (s.
strncpy [
http://www.cplusplus.com/reference/cstring/strncpy/]).
Ergänzung: Bedenke, daß aber hier der String dann nicht null-terminiert ist, d.h. die Ausgaben mittels
cout oder
printf dann ebenso UB sind!
Delete - Do 24.08.17 11:43
- Nachträglich durch die Entwickler-Ecke gelöscht -
hydemarie - Do 24.08.17 11:59
Frühlingsrolle hat folgendes geschrieben : |
Da müsste man mit strncpy() arbeiten. |
Je nach System. Der C11-Standard und Microsoft empfehlen
strncpy_s, ältere C-Standards
strncpy(), unter bestimmten Systemen mit bestimmten C-Standardbibliotheken bietet sich vielleicht eher
strlcpy() an. Und so weiter. :wink:
Ja, aber
cNeu ist hinterher immer noch
NULL. 8)
Th69 - Do 24.08.17 13:29
Dies gibt einen Compilerfehler (oder zumindestens eine Warnung):
Ideone-Code [
https://ideone.com/N27rzo], sofern
cNeu weiterhin als
char * deklariert ist, denn
*cNeu entspricht ja
cNeu[0], d.h. nur der Wert der Speicheradresse (also hier ein einzelnes Zeichen (
char)).
----------------
hydemarie hat folgendes geschrieben: |
Ja, aber cNeu ist hinterher immer noch NULL. |
Was meinst du damit??? Wie kommst du auf
NULL?
hydemarie - Do 24.08.17 13:42
Gegenfrage: Mit welchem Wert (nicht: Typ) ist cNeu denn initialisiert?
Th69 - Do 24.08.17 13:53
Wir reden (bzw. schreiben) hier doch von:
C++-Quelltext
1:
| char* cNeu = new char[3]; |
also hat
cNeu wohl einen anderen Wert als
NULL (und sollte
new keinen Speicher mehr allozieren können, dann gibt es eine
bad_alloc Exception).
hydemarie - Do 24.08.17 14:04
Th69 hat folgendes geschrieben : |
also hat cNeu wohl einen anderen Wert als NULL |
Nämlich?
Was ist denn der Standardwert eines
char?
Th69 - Do 24.08.17 14:12
Ich verstehe dich leider immer noch nicht. Bitte poste nochmals den gesamten Code, auf den du dich beziehst.
hydemarie - Do 24.08.17 14:20
Du behauptest,
cNeu habe einen anderen Wert als
NULL. Welchen hat er denn deiner Meinung nach? Das war doch eine eigentlich ganz einfach formulierte Frage.
Nachtrag:
C++-Quelltext
1:
| printf("cNeu ist %s\n", cNeu); |
Th69 - Do 24.08.17 14:36
cNeu ist ein Zeiger, d.h. es enthält eine Adresse:
Wenn du
C++-Quelltext
1:
| printf("cNeu ist %s\n", cNeu); |
ausgibst, dann gibt du den Inhalt als nullterminierten String aus, auf den
cNeu zeigt (das ist etwas ganz anderes - und
NULL wird dann auch nicht ausgegeben).
hydemarie - Do 24.08.17 14:44
Du hast meine Frage nicht beantwortet.
Der Wert, der an der Adresse, auf die der Zeiger zeigt, steht, ist was
, wenn nicht NULL?
Was ist der Standardwert eines nicht initialisierten
char*? :)
Th69 hat folgendes geschrieben : |
NULL wird dann auch nicht ausgegeben). |
Das liegt daran, dass
NULL nicht ausgegeben werden
kann. Auf
ideone steht da stattdessen
(null) ... ;)
Nachtrag:
Die ursprüngliche Frage war ja:
Ich
unterstelle, dass das so gemeint war, dass hinterher in
cNeu "Neu" drinsteht. @Frühlingsrolle mag mich diesbezüglich korrigieren. Die
Ausgabe von
cNeu ist und bleibt hinterher aber "leer".
Th69 - Do 24.08.17 14:53
Das ist UB, denn bei einem nicht-initialisierten Zeiger weiß man ja gar nicht, worauf der Zeiger zeigt (irgendeine beliebige Speicheradresse):
C++-Quelltext
1: 2: 3: 4: 5: 6:
| int main() { char *cNeu; printf("%x\n", cNeu); printf("%s\n", cNeu); } |
(Im Debug-Modus werden diese [lokalen Variablen] zwar von einigen Compilern mit 0 initialisiert, aber spätestens im Release-Modus führst dies zu undefinertem Verhalten).
Nachtrag:
Dein letzter Satz ist jetzt aber erst recht widersprüchlich:
Wenn da "Neu" drinsteht (also wenn man es korrekt z.B. mittels strncpy oder strcpy kopiert), dann wird auch "Neu" ausgegeben!
Warum sollte der vorher zugewiesene Zeiger auf einem mal NULL sein???
hydemarie - Do 24.08.17 14:56
Th69 hat folgendes geschrieben : |
Das ist UB, denn bei einem nicht-initialisierten Zeiger weiß man ja gar nicht, worauf der Zeiger zeigt |
Und wenn du ihn
ausgibst, ist das Verhalten in jedem mir bekannten Compiler gleich: Da steht dann "nichts" drin. ;)
(N.b.:
calloc() ist in vielen Fällen die deutlich bessere Wahl, wenn man sich über die Werte nicht ganz sicher ist.)
Delete - Do 24.08.17 17:22
- Nachträglich durch die Entwickler-Ecke gelöscht -
tomycat - Fr 25.08.17 08:16
hydemarie hat folgendes geschrieben : |
Du brauchst malloc/calloc beziehungsweise realloc zum Beispiel für C und damit auch die Interaktion mit C.
Konkreter Anwendungsfall: du möchtest eine Textdatei zeilenweise in eine Variable speichern. Da C keine std::strings und keine Vektoren kennt, bräuchtest du dafür zum Beispiel einen char**-Pointer. Die einzelnen Strings brauchen aber jedes Mal eine andere Anzahl an Byte, sie sind ja selten identisch.
C++-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| while (textfile) { char* next_line = strchr(textfile, '\n'); int linelength = next_line ? (next_line - textfile) : strlen(textfile); char* temp_str = (char *)malloc(linelength + 1);
if (temp_str) { memcpy(temp_str, textfile, linelength); temp_str[linelength] = '\0'; free(temp_str); }
textfile = next_line ? (next_line + 1) : NULL; } |
Absturz (Beispiel): Räume einen Speicherbereich frei, der dir nicht gehört.
C++-Quelltext 1: 2:
| int quux = 42; free(quux); | |
ok, wenn ich es richtig verstanden habe, lese ich eine Text Datei zeilenweise aus und jedesmal beantrage ich einen Speicherbereich. Erst am Ende mache ich den Speicher wieder frei?
hydemarie - Fr 25.08.17 09:20
Du machst den Speicher frei, sobald du ihn beziehungsweise den Wert nicht mehr brauchst. :)
Am Ende würde auch gehen, aber dann müsstest du realloc() (Neubelegen noch reservierten Speichers) für jede Zeile nutzen. Vorteil: du müsstest nur noch einmal aufräumen. Ist aber gefährlicher, was mögliche Memleaks, also auch nach dem Programmende noch belegten Speicher, betrifft, zum Beispiel bei Fehlern in der Schleife.
tomycat - Fr 25.08.17 16:10
ok,
Zeile 2: Wenn textfile Null, dann bricht die Schleife ab.
Zeile 3: Es wird Untersucht ob ein \n in textfile vorhanden ist, das wird in nextline gespeichert.
Zeile 4: ist nextline wahr, dann kommt es zu einer Subtaktion, ähh das geht ?!? Zeichenlänge wird berechnet
Zeile 5: Dann reserviere ich mir einen Speicherplatz für linelenth und weise Ihn dem temp_str zu, richtig?
Wird die If Abfrage ausgeführt, bei 10 Zeilen, 10 mal ausgeführt. Dann wird doch immer der Speicher wieder freigegeben?
hydemarie - Fr 25.08.17 16:18
Das ist so richtig, ja. :)
tomycat - Sa 26.08.17 00:20
hydemarie hat folgendes geschrieben : |
Das ist so richtig, ja. :) |
Aber warum kommt es dannn zu crash?
hydemarie - Sa 26.08.17 00:22
Wo?
tomycat - Mo 28.08.17 14:14
THX,
Ok, ich nehme an wenn ich free auskokumentiere, dann kommt es zum crash?!?
Woher weis ich, ok, jetzt brauche ich malloc?
Wo orientiere ich mich?
Wo ist die Grenze?
hydemarie - Mo 28.08.17 15:53
Wenn du irgendwo free() auskommentierst, dann hast du ein Speicherleck, aber keinen Absturz.
Es gibt keine Grenze. :)
tomycat - Mo 28.08.17 21:02
@hydemarie
danke dass du mich verstehst :-)
ok, dann habe ich ein Speicherleck, wieder was gelernt.
sorry, wenn ich nerve. Aber ich weis immer noch nicht, wann ich malloc verwenden soll?
Ich lass free weg, woher weis ich wann dann creash kommt, oder geht der Rechner in die Knie?
Nach was soll ich googlen?
hydemarie - Mo 28.08.17 21:10
tomycat hat folgendes geschrieben : |
sorry, wenn ich nerve. Aber ich weis immer noch nicht, wann ich malloc verwenden soll? |
Das sollte dir auch leid tun! :D
malloc() verwendest du überall dort, wo dir kein
RAII [
https://de.wikipedia.org/wiki/RAII] zur Verfügung steht, also meist im Umgang mit C-Schnittstellen oder wenn du direkt C benutzst.
tomycat hat folgendes geschrieben : |
Ich lass free weg, woher weis ich wann dann creash kommt |
Crash kommt, wenn das Programm plötzlich ausgeht. :!:
tomycat hat folgendes geschrieben : |
oder geht der Rechner in die Knie? |
Theoretisch könntest du mit
malloc() und daraus folgenden Speicherlecks einen Rechner quasi lahmlegen, ja.
Wenn du mehr Speicher belegst als du frei hast. Das kann aber auf heutigen Systemen dauern. ;)
Trotzdem solltest du das natürlich nicht vernachlässigen. Jedes weggeworfene Byte ist ein weggeworfenes Byte.
tomycat hat folgendes geschrieben : |
Nach was soll ich googlen? |
Grundsätzlich nach Taylor Swift. Die macht bessere Musik als es oft kolportiert wird. Thematisch allerdings empfehle ich allenfalls
Wikibooks [
https://de.wikibooks.org/wiki/C-Programmierung:_Speicherverwaltung].
tomycat - Di 29.08.17 16:35
danke, jetzt habe ich eine Richtung.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!