mikrocontroller.net

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


Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?
  start_of_output_string_ptr = output_string_ptr;
  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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum so kompliziert?
Kein Mensch braucht hier malloc
void draw_line(char x1, char y1, char x2, char y2)
{
  char Buffer[8];

  Buffer[0] = 0x1B;   // Escape
  Buffer[1] = 'G';
  Buffer[2] = 'D';
  Buffer[3] = y1;
  Buffer[4] = x1;
  Buffer[5] = y2;
  Buffer[6] = x2;
  Buffer[7] = '\0';

  send_frame( Buffer, 0x11 );
}


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

Wenns unbedingt malloc sein soll:
void draw_line(char x1, char y1, char x2, char y2)
{
  char* Buffer;

  Buffer = malloc( 8 * sizeof( char ) );

  if( Buffer != NULL ) {
    Buffer[0] = 0x1B;   // Escape
    Buffer[1] = 'G';
    Buffer[2] = 'D';
    Buffer[3] = y1;
    Buffer[4] = x1;
    Buffer[5] = y2;
    Buffer[6] = x2;
    Buffer[7] = '\0';

    send_frame( Buffer, 0x11 );
 
    free( Buffer );
  }
}

aber ausser mehr Laufzeit bringt das eigentlich nicht viel.

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
void draw_line(char x1, char y1, char x2, char y2)
{
  char Buffer[8];

  Buffer[0] = 0x1B;   // Escape
  Buffer[1] = 'G';
  Buffer[2] = 'D';
  Buffer[3] = y1;
  Buffer[4] = x1;
  Buffer[5] = y2;
  Buffer[6] = x2;
  Buffer[7] = '\0';

  send_frame( Buffer, 0x11 );
}

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

Gruß,
Harald

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald wrote:
> Hallo,
>
>
> void draw_line(char x1, char y1, char x2, char y2)
> {
>   char Buffer[8];
> 
>   Buffer[0] = 0x1B;   // Escape
>   Buffer[1] = 'G';
>   Buffer[2] = 'D';
>   Buffer[3] = y1;
>   Buffer[4] = x1;
>   Buffer[5] = y2;
>   Buffer[6] = x2;
>   Buffer[7] = '\0';
> 
>   send_frame( Buffer, 0x11 );
> }
> 
>
> 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).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Luther Blissett (Gast)
Datum:

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

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.