free nach malloc

MPNuts

Mitglied
Hi,

wie ist das mit der free Funktion?

In meinem Programm sind alle Arrays über die malloc Funktion erstellt. Jetzt habe ich gelesen, ich soll danach, wieder den Befehl free benutzen.

Die Arrays sollen wärend des gesamten Programmlaufs vorhanden sein.
Jetzt ist meine Frage, wo muss ich dann den Befehl ansetzen. In der Funktion die auch die malloc Funktion aufruft:

Code:
char * getarray (int index)
{
char * p;		//Pointer zur aufnahme des Arrays
p=(char*)malloc(index*sizeof(char)); //Das System wird nach Speicher gefragt
if (p==NULL)	 //Frage nach dem "NULL-Zeiger"
{
printf("Zu wenig Speicherplatz vorhanden");
}
return p;		//Rückgabe des Pointers mit dem Array
free(p);
}

Ist so das Array in der Funktion die das Array erhält dann noch da?

Oder soll ich das Array erst zum Schluss des Programms wieder löschen? Oder muss ich nach jeder Übergabe wenn die Funktion abgeschlossen ist das Array löschen?

Ich versteh das nicht so richtig.

Vorallem, wenn ich eines meiner Arrays erst zu Programm ende wieder löschen will stürzt mein Programm ab.
 
Der Aufruf von free(p) ist "unreachable code", will sagen: der Code wird nie ausgeführt. Freigeben mußt Du den Speicher dann, wenn das Array nicht mehr gebraucht wird. Also in Deinem Fall, wenn das Array immer vorhanden sein muß, wenn das Programm beendet wird. Der Programmabsturz hat vermutlich andere Ursachen, aber die kann man bei dem kurzen Stück Code freilich nicht erkennen...
 
Danke,

noch eine Frage, ist nicht ganz rübergekommen, ist es egal, in welcher Funktion ich die Arrays wieder aufhebe, oder muss ich sie mit dem Pointer wieder löschen mit dem ich sie auch erstellt habe.

Wenn ja, gäbe es ein Problem, da die Pointer ja nicht mehr existieren, da sie von einer Unterfunktion erstellt werden.

Warum kann ich das folgende Array nicht aufheben, es wir in einer der zwei Funktionen beschrieben, erstellt wird es in der Funktion oben.
Code:
char * indize (char * ar1, char * ar2, int a1 ,int a2)
{
char * arziel;
int index, z;
index=a1+a2; //Errechnen der Größe des Ziel-Arrays
arziel=getarray(index); //Aufruf(getarray), Ziel-Array wird erstellt
z=0;
for (int i=0; i < index; i++)
{
if (a1>=0) //Bis Array zuende
{
arziel[z]=ar1[a1];
z++;a1--;
} //Schreiben von Quell in Ziel-Array
 
if (a2>=0) //Bis Array zuende
{
arziel[z]=ar2[a2];
z++;a2--;
} //Schreiben von Quell in Ziel-Array
}
return arziel;
}
//////////////////////////////////////////////////////////////////////////////////////////////
///////// indize
//////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////
///////// deref
//////////////////////////////////////////////////////////////////////////////////////////////
char * deref (char * ar1, char * ar2, int a1 ,int a2)
{
char * arziel;
int index, z;
index=a1+a2; //Errechnen der Größe des Ziel-Arrays
arziel=getarray(index); //Aufruf(getarray), Ziel-Array wird erstellt
z=0;
for (int i=0; i < index; i++)
{
if (a1>=0) //Bis Array zuende
{
*(arziel+z)=*(ar1+a1);
z++;a1--;
} //Schreiben von Quell in Ziel-Array
if (a2>=0) //Bis Array zuende
{
*(arziel+z)=*(ar2+a2);
z++;a2--;
} //Schreiben von Quell in Ziel-Array
}
return arziel;
}
//////////////////////////////////////////////////////////////////////////////////////////////
///////// deref
//////////////////////////////////////////////////////////////////////////////////////////////

Was passiert wenn ich das Array einfach nicht wieder lösche?
 
Zuletzt bearbeitet:
noch eine Frage, ist nicht ganz rübergekommen, ist es egal, in welcher Funktion ich die Arrays wieder aufhebe, oder muss ich sie mit dem Pointer wieder löschen mit dem ich sie auch erstellt habe.

Das geht ohne Probleme, vorrausgetzt du gibst den Zeiger des erstellten Speichers
dem Aufrufer der Funktion auch wieder zurück,
somit besitzt deine aufrufende Funktion den Zeiger auf den in der aufgerufenen
Funktion besorgten Speicher und du kannst diesen ohne Probleme wieder mittels
delete oder free freigeben...

Was passiert wenn ich das Array einfach nicht wieder lösche?

Dann hast du ein Speicherleck, wenn dir die Referenz ( der Zeiger) auf den von
dir allokierten Speicher einmal verloren geht, hast du keine Möglickeit
diesen irgendwann wieder freizugeben, und somit verschwendest du den Speicher.

Warum kann ich das folgende Array nicht aufheben, es wir in einer der zwei Funktionen beschrieben, erstellt wird es in der Funktion oben.

Aus deinem Code ist für mich nicht ersichtlich wo du dieses tust...

Gruß

RedWing
 
Erstmal Danke für deine Hilfe.

Naja, das Problem ist, das Array wird wie gesagt, jetzt am ende wieder gelöscht, aber es wird in der Funktionshiraschie ganz unten erstellt aber erst wieder ganz oben gelöscht. dazwischen liegen 3 bis 4 Funktionen
getarray(hier wird es erstellt)->einlesen(es wird beschrieben)->verein(hier wird das nicht zu löschende Array erstellt)->indize oder deref (das nicht zu löschende Array wird mit den anderen beschrieben)->zurück an verein(char* p; p=deref(Array1, Array2))->main(hier soll es am ende gelöscht werden.
Code:
char * verein ()
{
char * ar1; //Pointer auf das erste Array
char * ar2; //Pointer auf das zweite Array
char * arziel; //Pointer auf das Ziel-Array
char a;	//Auswahl on Indizes oder Dereferentiert
int i;	//Zählvariablen
int a1, a2, index; //Größe der Arrays
do
{
do
{
printf("\nBitte geben Sie die erste Zeichenfolge ein:\n\t");
ar1=eingabe(); //Aufruf der eingabe Funktion, erstellen und beschreiben des Arrays
a1=--globalindex; //Der Index wird aus der globalen Variable geschrieben
printf("\nBitte geben Sie die zweite Zeichenfolge ein:\n\t");
ar2=eingabe(); //Aufruf der eingabe Funktion, erstellen und beschreiben des Arrays
a2=--globalindex; //Der Index wird aus der globalen Variable geschrieben
index=a1+a2; //Errechnen der Größe des Ziel-Arrays
printf("\n\nIst diese Eingabe korrekt?\nDuecken Sie 'j' um die Eingabe zu bestaetigen\n");
a=getch();
system("cls");
}while (a!='j');
a1--;
a2--; //Formatieren der Zählwerte
printf("\n\t1. Dereferenziert\n\t2. Indizes");
a=getch();
system("cls");
if (a=='1') //Auswahl welche Sotierfunktion benutzt wird
{
arziel=deref(ar1, ar2, a1, a2);
}else	//Aufruf der Sotierfunktion mit Dereferenzierung
{
arziel=indize(ar1, ar2, a1, a2);
}	 //aufruf der Sotierfunktion mit Indizes
a1++;a2++;
printf("\n\t1. Zeichenkette\t: ");
for (i=0; i < a1; i++)//Ausgabe des ersten Arrays
{
printf("%c", ar1[i]);
}
printf("\n\t2. Zeichenkette\t: ");
for (i=0; i < a2; i++)//Ausgabe des zweiten Arrays
{
printf("%c", ar2[i]);
}
printf("\n\n\tZiel-Array\t: ");
for (i=0; i < index; i++)//Ausgabe des Zielarrays
{
printf("%c", arziel[i]);
}
 
globalindex=index; 
 
free(ar1); //Speicherplatz wir wieder freigegeben
free(ar2);
printf("\n\nSind Sie mit dem Ergebnis unzufrieden?\n\tDann druecken Sie 'j', ");
printf("jede andere Taste um fortzufahren.");
a=getch();
system("cls");
}while (a!='j');
return arziel;
}
Code:
//////////////////////////////////////////////////////////////////////////////////////////////
///////// main
//////////////////////////////////////////////////////////////////////////////////////////////
void main ()
{
char * p;
int prend, index;
char a;
 
do
{
system("cls");
printf("\n\t\t\tMenue\n\n\t\tStart \t\t[s]\n\t\tVeraendern \t[v]\n\t\tAbout \t\t[a]");
printf("\n\t\tBeenden \t[b]");
a=getch();
system("cls");
switch (a)
{
case('s'):{ //Aufruf von f(verein)
p=verein();
index=globalindex;
prend=1;
break;}
case('v'):{ //Aufruf von f(veraender)
veraender(p, index);
prend=1;
break;}
case('b'):{ //Abbruchbedingung der Schleife
prend=-1;
printf("\n\n\t\t");
break;}
case('a'):{ //Aufruf der Programmbeschreibung
about();
prend=1;
break;}
default:{ //Wiederholung der Schleife
prend=1;}
}
} while (prend>0);
free(arziel);
}

Naja, so sieht das Programm aus, schon mal danke, wenn sich einer die Mühe macht das durchzusehen, auch der Quellcode in meinem letztzen Post gehören dazu. Alle Fett gedruckten dinge bezeihen sich auf das bestimmte Array
 
Zuletzt bearbeitet:
Code:
while (prend>0);
free(arziel);
}
Hi,
also ich hoff mal ich hab deinen Code jetzt richtig entziffert,

1.) Das while kannst du dir sparen, da der Speicher eh nur im ersten case Label allokalisiert
wird...
So würde es leserlicher ausschauen:
Code:
char *p = NULL;
switch(...){
  case 's': Speicher allokalisieren; break;
  ...
}
...
if(p != NULL)
   free(p);

2.) Wie man am obigen Codeschnipsel sieht musst du p freigeben und nicht arziel, arziel ist
in deiner main Funktion gar nicht deklariert sondern nur in deinen anderen Funktionen
bekannt und die geben ja den Pointer arziel an p im main zurück, somit zeigt p auf den
Speicher der irgendwo in deinen Funktionen allokalisiert wurde.

Gruß

RedWing
 
Danke für die Mühe, war bestimmt nicht sehr spassig!

RedWing hat gesagt.:
Hi,
also ich hoff mal ich hab deinen Code jetzt richtig entziffert,

1.) Das while kannst du dir sparen, da der Speicher eh nur im ersten case Label allokalisiert
wird...
So würde es leserlicher ausschauen:
Code:
char *p = NULL;
switch(...){
case 's': Speicher allokalisieren; break;
...
}
...
if(p != NULL)
free(p);

RedWing
Das while gehört zum do->while, ist, dass das Programm immer wieder von vorne beginnt.

Mit deinem Beispiel klappt es leider auch nicht in meinem Programm, aber ich habe heute in der FH erfahren, dass ein anderer das selbe Problem hat. Kann es sein, dass man so wie die Arrays erstellt wurden sie nicht mehr löschen kann? Aber was dagegen spricht, zwei der drei Arrays lassen sich problemlos wieder löschen, nur das indem die Daten der beiden anderen gespeichert werden nicht.
Kann ich eigentlich auch p=NULL schreiben? Ginge das?

Sollte ich Pointer immer mit einem Wert füllen, wie wenn es noch nicht feststeht mit =NULL?

RedWing hat gesagt.:
2.) Wie man am obigen Codeschnipsel sieht musst du p freigeben und nicht arziel, arziel ist
in deiner main Funktion gar nicht deklariert sondern nur in deinen anderen Funktionen
bekannt und die geben ja den Pointer arziel an p im main zurück, somit zeigt p auf den
Speicher der irgendwo in deinen Funktionen allokalisiert wurde.
RedWing
Ich hatte das noch schnell nur im Post eingefügt, da es ja nicht funktionierte, habe ich es aus meinem Programm schon entfernt gehabt, und mich dann natürlich gleich in der Variablen vergriffen. SORRY!
 
Zurück