Forum: Compiler & IDEs Atmega32: malloc stürzt bei mehrfachem Aufruf ab


von Harald (Gast)


Lesenswert?

Hallo,

Kummer macht diese Funktion:


<code>
void draw_line(char x1, char y1, char x2, char y2)
{

  char start_of_output_string;
  char output_string;
  char *start_of_output_string_ptr;
  char *output_string_ptr;

  start_of_output_string_ptr = &start_of_output_string;
  //output_string_ptr = &output_string;

  output_string_ptr = (char *) malloc(7*sizeof(char));
  start_of_output_string_ptr = output_string_ptr;
  output_string_ptr = start_of_output_string_ptr;
  *output_string_ptr = 0x1B;  //<ESC>
  output_string_ptr++;
  *output_string_ptr = 'G';  //Geometrie
  output_string_ptr++;
  *output_string_ptr = 'D';   //Gerade
  output_string_ptr++;
  *output_string_ptr = y1;  //Koordinaten
  output_string_ptr++;
  *output_string_ptr = x1;
  output_string_ptr++;
  *output_string_ptr = y2;
  output_string_ptr++;
  *output_string_ptr = x2;
  output_string_ptr++;
  *output_string_ptr = 0x00;
  output_string_ptr = start_of_output_string_ptr;
  send_frame(output_string_ptr, 0x11);
  free(output_string_ptr);
}
</code>

Wenn ich obige Funktion ein zweites mal im Haupprogramm aufrufe, wird 
die bis zum malloc() ausgeführt und bleibt dort stehen. Ich komme 
einfach nicht dahinter, was da schief läuft. Vielleicht ein 
Speicherleck?
Die Funktion dient zur Ansteuerung eines Graphik-LCD über SPI.

Gruß,
Harald

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du wertest den Rückgabewer von malloc nicht aus, daher ist nicht sicher, 
daß auch nur der erste Aufruf geklappt hat. Deine Schreibzugriffe auf 
output_string_ptr können also irgendwo im Speicher herumschreiben mit 
welchen Folgen auch immer.

Was soll das hier?
1
  start_of_output_string_ptr = output_string_ptr;
2
  output_string_ptr = start_of_output_string_ptr;

Im übrigen forderst Du Platz für 7 Bytes an, schreibst aber 8.

Was ist der zweite Parameter von send_frame? Hoffentlich nicht die 
Puffergröße.

Meinst Du außerdem, daß es sinnvoll ist, für einen Puffer von gerade 
mal 7 (naja, eigentlich 8) Bytes Länge auf dynamische Speicherverwaltung 
zu setzen?

von Karl H. (kbuchegg)


Lesenswert?

Warum so kompliziert?
Kein Mensch braucht hier malloc
1
void draw_line(char x1, char y1, char x2, char y2)
2
{
3
  char Buffer[8];
4
5
  Buffer[0] = 0x1B;   // Escape
6
  Buffer[1] = 'G';
7
  Buffer[2] = 'D';
8
  Buffer[3] = y1;
9
  Buffer[4] = x1;
10
  Buffer[5] = y2;
11
  Buffer[6] = x2;
12
  Buffer[7] = '\0';
13
14
  send_frame( Buffer, 0x11 );
15
}


Ich denke, du hast dich da irgendwo mit den Pointer-Umkopier-
Aktionen selbst in den Wald geschickt.

Wenns unbedingt malloc sein soll:
1
void draw_line(char x1, char y1, char x2, char y2)
2
{
3
  char* Buffer;
4
5
  Buffer = malloc( 8 * sizeof( char ) );
6
7
  if( Buffer != NULL ) {
8
    Buffer[0] = 0x1B;   // Escape
9
    Buffer[1] = 'G';
10
    Buffer[2] = 'D';
11
    Buffer[3] = y1;
12
    Buffer[4] = x1;
13
    Buffer[5] = y2;
14
    Buffer[6] = x2;
15
    Buffer[7] = '\0';
16
17
    send_frame( Buffer, 0x11 );
18
 
19
    free( Buffer );
20
  }
21
}

aber ausser mehr Laufzeit bringt das eigentlich nicht viel.

von Harald (Gast)


Lesenswert?

Hallo,


>Was soll das hier?

>  start_of_output_string_ptr = output_string_ptr;
>  output_string_ptr = start_of_output_string_ptr;

Das ist das Fragment einer früheren Version, das ich wohl übersehen 
habe.

>Im übrigen forderst Du Platz für 7 Bytes an, schreibst aber 8.

Hoppla.

>Was ist der zweite Parameter von send_frame? Hoffentlich nicht die
>Puffergröße.

Nein, das ist eine von zwei Headervarianten, die es im speziellen 
Protokoll des LCDs gibt.

Gruß,
Harald

von Harald (Gast)


Lesenswert?

Hallo,
1
void draw_line(char x1, char y1, char x2, char y2)
2
{
3
  char Buffer[8];
4
5
  Buffer[0] = 0x1B;   // Escape
6
  Buffer[1] = 'G';
7
  Buffer[2] = 'D';
8
  Buffer[3] = y1;
9
  Buffer[4] = x1;
10
  Buffer[5] = y2;
11
  Buffer[6] = x2;
12
  Buffer[7] = '\0';
13
14
  send_frame( Buffer, 0x11 );
15
}

muß ich dann hier nicht noch die Anzahl der Array-Elemente mitübergeben?

Gruß,
Harald

von Karl H. (kbuchegg)


Lesenswert?

Harald wrote:
> Hallo,
>
>
1
> void draw_line(char x1, char y1, char x2, char y2)
2
> {
3
>   char Buffer[8];
4
> 
5
>   Buffer[0] = 0x1B;   // Escape
6
>   Buffer[1] = 'G';
7
>   Buffer[2] = 'D';
8
>   Buffer[3] = y1;
9
>   Buffer[4] = x1;
10
>   Buffer[5] = y2;
11
>   Buffer[6] = x2;
12
>   Buffer[7] = '\0';
13
> 
14
>   send_frame( Buffer, 0x11 );
15
> }
16
>
>
> muß ich dann hier nicht noch die Anzahl der Array-Elemente mitübergeben?
>

an wen?

Die Funktion macht nichts anderes als deine gepostete Version.
Nur ist sie einfacher, kürzer, (wahrscheinlich schneller),
hat keinen Array Overflow Bug und auch malloc kann dir nicht
in die Quere kommen.

Wenn deine ursprüngliche Version ausser dem malloc Problem,
noch ein anderes logisches Problem hatte, dann hat sie diese
Version auch. Aber das kann ich von hier aus nicht beurteilen
(ZB. kommt mir das komisch vor, dass die Koordinaten nur ein
char sind. Aber das musst du wissen).

von Karl H. (kbuchegg)


Lesenswert?

Ich glaube ich hab jetzt eine Ahnung was dir Kopfzerbrechen macht.


Die Funktion send_frame möchte als erstes Argument einen Pointer
haben. Buffer ist aber ein Array


Lektion 5 oder 6 in der C Programmierung für Anfänger:
Arrays werden in C immer an Funktionen übergeben, indem die
Startadresse des Arrays übergeben wird.

Hier:
   send_frame( Buffer, 0x11 );
wird tatsächlich die Startadresse des Arrays (in Form eines
Pointers) übergeben.

von Luther Blissett (Gast)


Lesenswert?

Man würde es idR. wohl so machen:
1
void draw_line(char x1, char y1, char x2, char y2)
2
{
3
  const char buf[]={0x1b,'G','D',y1,x1,y2,x2,'\0'}; 
4
  send_frame(buf,0x11); 
5
}

Bzw. mit gcc:
1
inline void draw_line(char x1, char y1, char x2, char y2)
2
{
3
  send_frame((char[]){0x1b,'G','D',y1,x2,y2,x2,'\0'},0x11); 
4
}

von Karl H. (kbuchegg)


Lesenswert?

Luther Blissett wrote:
> Man würde es idR. wohl so machen:

Yep. Das sind dann schon die Luxusversionen.
Wobei: Alle 3 Versionen schlagen mit einer identischen
Code-Größe zu Buche. Lediglich der Schreibaufwand ist geringer.


Trotzdem kommt mir das immer noch seltsam vor.
Für X1, y1, x2, y2 würde ich mal auf Koordinaten tippen.
Und 0 soll ja unter den Koordinaten nicht so unüblich selten
sein. Ich frage mich wie das dann funktionieren soll.
Aber ev. gehen die Koordinaten ja auchnur von 0 bis 9 und
werden als die entsprechenden ASCII Code gesendet, oder
es wird zur Zahl ein entsprechender Offset (ausserhalb
der Funktion) addiert oder ...
Möglich ist es, dass das so richtig ist. Aber seltsam ist
es doch.

von Peter D. (peda)


Lesenswert?

Es gibt nur 2 Gründe, um malloc zu benutzen.


1. Die Puffergröße ist zur Compilezeit unbekannt.

Dann sollte man aber erstmal prüfen, ob man den Puffer nicht mit der zu 
erwartenden Maximalgröße anlegt.
Denn malloc kann auch nicht mehr herzaubern, als verfügbar ist.


2. Der Puffer muß über den Erzeuger hinaus bestehen.

Dann sollte man aber erstmal prüfen, ob man nicht eine Oberfunktion 
definiert, die nur den Puffer anlegt und erst nach dem Nutzer 
terminiert.
Bzw. ob es überhaupt was bringt, den Puffer vor Ende des Main 
freizugeben.


Peter

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.