Forum: PC-Programmierung malloc() Programm terminiert nicht


von Felix W. (catchup)


Lesenswert?

Guten Abend,
ich bin derzeit dabei ein C Programm zu schreiben, um int Zahlen aus
einer Liste
einzulesen und zu sortieren. Meine Idee war die Listengröße in einer
Funktion auszulesen und dementsprechend den Speicher mit malloc() zu
reservieren. Anschließend soll dem reservierten Speicher die einzelnen
Elemente zugewiesen werden. Das Programm läuft nur terminiert es nicht.
Würde mich freuen, falls mir jemand weiterhelfen könnte.


Rückgabewert von fscanf() wurde beim ersten Aufruf der Funktion 
einlesen_size() schon aufgerufen und geprüft.
1
int *einlesen_array()
2
{
3
  int *array; //Pointer bzw. Array
4
  FILE *ptr; //Pointer der auf Beginn des Files zeigt
5
  int size = einlesen_size();  //dynamische Arrayanpassung als Laufvariable
6
  int i;
7
  
8
  //Pointer auf Beginn von Pfad definiert   
9
   ptr = fopen(pfad, "r");
10
  /********************************
11
   * Arraydefinition über malloc()*
12
   *******************************/
13
  array = (int *) malloc(size * sizeof(int));
14
15
  if (array == NULL)
16
  {
17
    printf("Speicher voll!\n");
18
    printf("Bitte Programm neustart.\n");
19
    return 0;
20
  }
21
  /**********************************
22
   * Füllen des Arrays mit Elementen*
23
   *********************************/
24
  for(i=0; i<size; i++)
25
  {
26
    fscanf(ptr,"%d",&array[i]);
27
  }
28
  free(ptr);
29
  return array;
30
}

der return soll in Funktion einer Funktion sort() dann sortiert werden.
Durch herausprobieren habe ich gemerkt, dass die obige Funktion mein 
Programm am terminieren hindert, ich verstehe aber nicht wieso.
LG Felix

von Theor (Gast)


Lesenswert?

In dem anderen Thread sind Dir sinnvolle Antworten gegeben worden.
Beitrag "malloc() return Array (Programm terminiert nicht)"

von Rolf M. (rmagnus)


Lesenswert?

Gibt einlesen_size() denn das richtige zurück (Dateigröße / 
sizeof(int))?

Und:
Felix W. schrieb:
> free(ptr);

Eine Datei schließt man mit fclose(), nicht mit free().

von zitter_ned_aso (Gast)


Lesenswert?

Felix W. schrieb:
> der return soll in Funktion einer Funktion sort() dann sortiert werden.

Und wie soll die Funktion herausfinden wie groß dein Array ist? Die 
Arraygröße wird ja in deiner Funktion(oben) lokal ermittelt. (und 
zurückgegeben wird nur die Arrayadresse)

von imonbln (Gast)


Lesenswert?

Felix W. schrieb:
> /********************************
>    * Arraydefinition über malloc()*
>    *******************************/
>   array = (int *) malloc(size * sizeof(int));

Mein Prof. hätte zu den Kommentar gesagt, "Ich kann lesen!", ein 
Kommentar sollte sagen, warum man etwas macht und nicht was man macht.

Außerdem solltest du das malloc so schreiben:

1
 array = malloc( size * sizeof(*array))

Im C Standard wird dir garantiert das sich jeder Pointer nach (void *) 
und wieder zurück casten lassen kann, ohne Eigenschaften zu verlieren. 
Das heißt in diesen Fall, das der cast vom C Standard geschützt auch 
implizit gemacht werden kann. Zusammen mit den sizeof des 
dereferenzierten Array, sorgt der Code dafür das, wenn Array auf long 
geändert wird das nur in der Deklaration gemacht werden muss und nicht 
alle mallocs überprüft werden müssen.

Achtung, dass mit der implizieren cast geht nicht, wenn man einen C++ 
Compiler verwendet (aber dann sollte man besser C++ Code schreiben und 
kein malloc verwenden)

Felix W. schrieb:
> printf("Bitte Programm neustart.\n");
>     return 0;

Return 0, ist bei den meisten Programmen ein Erfolg, von daher ist der 
Return code verwirrend. Außerdem gibt dein Programm einen Pointer 
zurück, statt ein Integer und hier sind sich eigentlich alle einig, dass 
eine solche Funktion im Fehlerfall NULL zurückgeben sollte. Zwar ist
1
((void *) 0)
 eine gültige Definition von NULL, du solltest aber dennoch besser NULL 
schreiben, um es den Leser einfacher zu machen, Sourcecode wird immer 
öfter gelesen als geschrieben, daher ergibt es Sinn auf das einfache 
Verstehen zu optimieren.

Felix W. schrieb:
> fscanf(ptr,"%d",&array[i]);

Denn return wert prüfen und eine gescheite Fehlerbehandlung einzubauen 
tut nicht hier nicht weh.

Felix W. schrieb:
> free(ptr);

Auch wenn das vielleicht suggeriert wird ist
1
FILE *ptr
 kein Filepointer, sondern ein Filehandle die Operation sollte also 
fclose sein und nicht free, btw ptr ist mir den wissen vielleicht ein 
suboptimaler Name.

von Rolf M. (rmagnus)


Lesenswert?

imonbln schrieb:
> Mein Prof. hätte zu den Kommentar gesagt, "Ich kann lesen!", ein
> Kommentar sollte sagen, warum man etwas macht und nicht was man macht.

Ja. Was man macht, sollte sich aus dem Code ergeben. Ein Kommentar, der 
nichts weiter ist als eine Prosa-Version einer Quelltextzeile, ist in 
der Regel nicht hilfreich.

> Außerdem solltest du das malloc so schreiben:
>
>  array = malloc( size * sizeof(*array))
> Im C Standard wird dir garantiert das sich jeder Pointer nach (void *)
> und wieder zurück casten lassen kann, ohne Eigenschaften zu verlieren.
> Das heißt in diesen Fall, das der cast vom C Standard geschützt auch
> implizit gemacht werden kann.

Das Wording ist nicht ganz präzise. Einen impliziten Cast gibt es nicht. 
Es handelt sich um eine implizite Konvertierung. Ein Cast ist das, was 
man hinschreibt, wenn man explizit eine Konvertierung auslösen will.

> Auch wenn das vielleicht suggeriert wird ist FILE *ptr kein Filepointer,
> sondern ein Filehandle die Operation sollte also fclose sein und nicht free,
> btw ptr ist mir den wissen vielleicht ein suboptimaler Name.

Ein Pointer ist es schon. Er zeigt aber nicht auf mit malloc() und 
Konsorten angeforderten Speicher, daher darf man darauf free() nicht 
anwenden.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.