Atmega32: malloc stürzt bei mehrfachem Aufruf ab

Gast #804688
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
Persönliche Seite #804702
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?
#804706
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.
Gast #804928
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
Gast #804932
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
#804961
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).
#804966
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.
Gast #804975
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
}
#804983
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.
#805606
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren