Problem mit malloc
-
eine frage noch: was passiert, wenn ich den mit malloc reservierten speicher nicht mehr mit free freigebe, sondern das programm einfach beende? was passiert dann, bzw. was könnte dann passieren?
-
noch eine frage schrieb:
eine frage noch: was passiert, wenn ich den mit malloc reservierten speicher nicht mehr mit free freigebe, sondern das programm einfach beende? was passiert dann, bzw. was könnte dann passieren?
Dann wird der Speicher nicht freigegeben. Was genau daraus resultiert hängt davon ab, wo das Programm läuft. Auf einem Multitaskingbetriebssystem mit virtueller Speicherverwaltung wird es keine ernsthaften Konsequenzen haben (außer Speicherdebugger zu verwirren und deinen Programmierstil zu verschlechtern), auf einem embedded Gerät kann aber auch der Speicher dadurch verloren sein.
-
SeppJ schrieb:
noch eine frage schrieb:
eine frage noch: was passiert, wenn ich den mit malloc reservierten speicher nicht mehr mit free freigebe, sondern das programm einfach beende? was passiert dann, bzw. was könnte dann passieren?
Dann wird der Speicher nicht freigegeben. Was genau daraus resultiert hängt davon ab, wo das Programm läuft. Auf einem Multitaskingbetriebssystem mit virtueller Speicherverwaltung wird es keine ernsthaften Konsequenzen haben (außer Speicherdebugger zu verwirren und deinen Programmierstil zu verschlechtern), auf einem embedded Gerät kann aber auch der Speicher dadurch verloren sein.
aber doch nur bis zum neustart?!?
-
______malloc schrieb:
SeppJ schrieb:
noch eine frage schrieb:
eine frage noch: was passiert, wenn ich den mit malloc reservierten speicher nicht mehr mit free freigebe, sondern das programm einfach beende? was passiert dann, bzw. was könnte dann passieren?
Dann wird der Speicher nicht freigegeben. Was genau daraus resultiert hängt davon ab, wo das Programm läuft. Auf einem Multitaskingbetriebssystem mit virtueller Speicherverwaltung wird es keine ernsthaften Konsequenzen haben (außer Speicherdebugger zu verwirren und deinen Programmierstil zu verschlechtern), auf einem embedded Gerät kann aber auch der Speicher dadurch verloren sein.
aber doch nur bis zum neustart?!?
Natürlich, aber man sollte den Benutzer nicht dazu zwingen, das Gerät nach einer bestimmten Zeit neu starten zu müssen. Idealerweise sollte es unbegrenzt lange laufen können.
-
Z schrieb:
Natürlich, aber man sollte den Benutzer nicht dazu zwingen, das Gerät nach einer bestimmten Zeit neu starten zu müssen. Idealerweise sollte es unbegrenzt lange laufen können.
gut, dachte nämlich, der speicher sei dann kaputt oder so und kann garnicht mehr freigegeben werden
-
Wenn du mal im Fahrstuhl festhängst, weil dieser seit 10 Jahren bei jeder Fahrt ein kleines Speicherleck hatte und dadurch nun endgültig festsitzt, dann überlegst du dir vielleicht nochmal, ob man sich immer auf einen Neustart verlassen sollte
-
ok, dann hab ich jetzt allso die datei in einen buffer geladen.
das problem ist, dass ich dann eine art array hab. da das ganze eine binärdatei ist, muss ich auch zahlen aus der datei lesen, normalerweise hätte ich das jetzt so gemacht:
int i; fread(&i,1,sizeof(int),datei);
ich hab versucht, dass zu übertragen:
int i; fread(&i,1,sizeof(int),(FILE*) buffer);
da stürzt mein programm wieder ab...
wie kann ich also vom speicher lesen? wie gesagt, ich weiß, dass ich auf den speicher wie ein array zugreifen kann.
-
Merke: Wenn du einen nicht-void-Zeiger hart umcasten musst, dann machst du meistens was falsch. Ein Dateizeiger ist kein Zeiger auf den Dateiinhalt, sondern auf eine komplexe Datenstruktur, den Dateihandle, der dann von fread ausgewertet wird (in der Struktur steht dann, wie man an den Inhalt der Datei kommt). Das geht natürlich grandios schief, wenn der Zeiger stattdessen auf irgendwelche Nutzdaten zeigt, die dann als solch ein Dateihandle interpretiert werden.*
Klingt eher nach einem Fall für memcpy.
*: Ja, mir ist bewusst, dass der Dateihandle in der Praxis oft einfach ein int ist. Aber es ist ein int mit dem richtigen Wert.
-
SeppJ schrieb:
*: Ja, mir ist bewusst, dass der Dateihandle in der Praxis oft einfach ein int ist. Aber es ist ein int mit dem richtigen Wert.
Ein Handle ist ein bisschen wenig für gepufferte Ein-/Ausgabe. Du solltest vielleicht mal in die stdio.h deiner Implementation schauen, wie dort FILE definiert ist. Bei mir ist das ein relativ fettes struct, ich habs auch noch nie wirklich anders gesehen.
-
hallo,
es tut mir leid, aber ich muss diesen thread nochmal pushen, weil ich eine neue frage hab.
hier erstmal mein code:
#include <string.h> #include <stdlib.h> #include <stdio.h> int test_funktion(char *memory,int s) { memory=(char *)malloc(s); // s bytes reservieren if(memory==NULL) { return 1; // 1 zurück, wenn kein speicherplatz alloziert wurde... } return 0; //... sonst 0 zurücl } int main() { char *memory; int return_var=test_funktion(memory,200); // 200 bytes reservieren printf("%d\n",return_var); free(memory); return 0; }
ich kompiliere diesen quellcode mit gcc. hier der vollständige compiler-aufruf
gcc -o test test.c -Wall
der gcc erzeugt eine warnung:
test.c: In Funktion »main«:
test.c:19:6: Warnung: »memory« wird in dieser Funktion uninitialisiert verwendet [-Wuninitialized]wenn ich das programm ausführe, kommt es anscheinend zu irgendeinem memory-fehler, auf jeden fall wird eine menge zeugs ausgegeben, irgendwas mit
===== Backtrace: =====
.
.
.
und
===== Memory map: ======
.
.
.
anscheinend irgendwas mit dem speicher... aber was?
-
Steht doch da: memory wird unitialisiert benutzt. Merke: Der Compiler hat immer Recht. Du hingegen solltest dir nochmal Parameterübergabe an Funktionen ansehen, insbesondere call by reference, bzw. die Übergabe per Pointer die man in C benutzen muss, um diesen Effekt zu erreichen. Tipp: Wenn du
void foo(int* a);
benutzen musst, um einen int zu verändern, was ist wohl nötig um einen Zeigertypen zu verändern?Bevor du dich aber zu sehr auf diese Lösung versteifst (Referenzübergabe solltest du trotzdem lernen): Designtodsünde! Nicht fortfahren, sofort umkehren. Man übergibt keine Verantwortung aus einer Funktion heraus oder hinein! Für das Freigeben von Ressourcen ist immer die Programmlogikebene verantwortlich, die diese auch angefordert hat. Wenn du dich nicht daran hältst, endet das so sicher in Spaghetticode wir goto und globale Variablen.
Im übrigen ist es schön zu sehen, dass du anscheinend nicht den Tipp mit dem Cast angeguckt hast und stattdessen immer noch deinem Schrottlehrbuch/-tutorial folgst.
-
SeppJ schrieb:
Steht doch da: memory wird unitialisiert benutzt. Merke: Der Compiler hat immer Recht. Du hingegen solltest dir nochmal Parameterübergabe an Funktionen ansehen, insbesondere call by reference, bzw. die Übergabe per Pointer die man in C benutzen muss, um diesen Effekt zu erreichen. Tipp: Wenn du
void foo(int* a);
benutzen musst, um einen int zu verändern, was ist wohl nötig um einen Zeigertypen zu verändern?Bevor du dich aber zu sehr auf diese Lösung versteifst (Referenzübergabe solltest du trotzdem lernen): Designtodsünde! Nicht fortfahren, sofort umkehren. Man übergibt keine Verantwortung aus einer Funktion heraus oder hinein! Für das Freigeben von Ressourcen ist immer die Programmlogikebene verantwortlich, die diese auch angefordert hat. Wenn du dich nicht daran hältst, endet das so sicher in Spaghetticode wir goto und globale Variablen.
Im übrigen ist es schön zu sehen, dass du anscheinend nicht den Tipp mit dem Cast angeguckt hast und stattdessen immer noch deinem Schrottlehrbuch/-tutorial folgst.
also irgendwie versteh ich deinen beitrag nicht, obwohl ich schon länger c lerne
du meinst also ich soll, wenn ich etwas mit einem char-pointer in einer funktion machen will, eine char pointer zurückgeben, und kein int? aber wie soll ich denn dann andere rückgabe-werte zurückgeben (z.b. wenn ein fehler auftritt.)
meinst du das jetzt so:
char *test_funktion(char *memory,int s) { memory=(char *)malloc(s); if(memory==NULL) { return 1; } return memory; }
... oder wie?
-
p.s.: anscheinend hab ich hier was überlesen... was meinst du mit dem "cast"? mach ich das nicht bei malloc ("**(char *)**malloc....")?
-
Einen Cast dieser deiner "Güte" setzen nur Leute ein, die nicht wissen, was sie machen oder/und wollen (C oder C++).
Zu einem malloc gehört auch immer ein free, und das free muss für ein sinnvolles Design immer auf derselben Funktions(Aufruf)-Ebene liegen, wie das malloc, also in etwaint main() { char *p=malloc(100); if( funktion(p)==irgendeinfehlercode ) { ... } free(p); ... }
-
*** edit *** schrieb:
p.s.: anscheinend hab ich hier was überlesen... was meinst du mit dem "cast"? mach ich das nicht bei malloc ("**(char *)**malloc....")?
Warum tust du das?
du meinst also ich soll, wenn ich etwas mit einem char-pointer in einer funktion machen will, eine char pointer zurückgeben, und kein int?
Nein. Das war ein Beispiel, damit ich dir nicht die Lösung vorkaue und du nichts kapierst. Versuch mal drüber nachzudenken, was ich gesagt habe.
meinst du das jetzt so:
WTF?
Nein, so meinte ich das ganz sicher nicht.Aufgabe 1:
int a = 1; foo(a); printf("%d", a);
Schreibe eine Funktion foo, so dass dieses Programm "0" ausgibt.
Aufgabe 2:
int i; int *a = &i; bar(a); printf("%p", a);
Schreibe eine Funktion bar, so dass dieses Programm "0x0" ausgibt. Tipp: Vielleicht hilft es, die Lösung von Aufgabe 1 zu verstehen und nicht aus dem Internet/Lehrbuch zu kopieren. Beim Programmieren musst du von jedem Zeichen in deinem Programm wissen, was es bedeutet und warum du es setzt.
-
ok das hab ich jetzt verstanden.
also darf wohl eine "externe" funktion (ich mein damit funktionen außerhalb der hauptfunktion) keinen speicherplatz allozieren, bzw. freigeben?
-
SeppJ schrieb:
Aufgabe 1:
int a = 1; foo(a); printf("%d", a);
Schreibe eine Funktion foo, so dass dieses Programm "0" ausgibt.
Aufgabe 2:
int i; int *a = &i; bar(a); printf("%p", a);
Schreibe eine Funktion bar, so dass dieses Programm "0x0" ausgibt. Tipp: Vielleicht hilft es, die Lösung von Aufgabe 1 zu verstehen und nicht aus dem Internet/Lehrbuch zu kopieren. Beim Programmieren musst du von jedem Zeichen in deinem Programm wissen, was es bedeutet und warum du es setzt.
ich blicks einfach nicht mit diesen pointern...
Aufgabe 1:
das wär jetzt meine idee:void foo(int *a) { &a=0; }
Aufgabe 2:
void bar(int *a) { *a=0; }
lösung?
-
Die compilieren nicht einmal. Nicht raten. Programmieren. Dazu gehört auch, seine Programme mal auszuprobieren. Oder auch mal den Stolz zu überwinden und ins dritte Kapitel des Lehrbuchs zurück zu springen.
-
Pointer sind auch nur Variablen.
Sie haben halt Adressen als Werte.Und man kann auch die Adresse bestimmen, wo ein Pointer seinen Wert abspeichert.
-
+++--- schrieb:
void foo(int *a) { &a=0; }
'&' steht in diesem Fall für den Adress-Operator, du musst verstehen, dass du eine Adresse prinzipiell nicht ändern kannst, du kannst nur die Daten, die an dieser Adressen stehen, lesen und schreiben, und dafür sind Zeiger da und hierbei insbesondere die Dereferenzierung eines Zeigers mittels '*'.