Forum: Mikrocontroller und Digitale Elektronik [Glaskugel] Funktionsaufruf lässt Controller hängen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von D a v i d K. (oekel) Benutzerseite


Bewertung
-1 lesenswert
nicht lesenswert
Hi,

wie die Überschrift vermuten lässt erwarte ich keine Wunder.
Aber vielleicht fällt dem ein oder anderem etwas dazu ein?
(Falls nicht bitte einfach weiter gehen :P)

...wieso der folgende Code beim einmaligen und zweimaligen Aufruf 
passiert werden kann, jedoch bei 3-maligem Aufruf den Atmega16 zum 
hängen bringt.
(Meine Annahme, dass er hängen bleibt beruht auf der Ausgabe auf einem 
2x16 Zeilen-Display bzw. der NICHT Ausgabe der sofort folgendem 
Zeilenausgabe auf demselbigen.)
1
//mein "Werk"
2
void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros) {
3
  char str[c];
4
  utoa(value, str, 10);
5
  if (leadingZeros) {
6
    for (uint8_t i = getDigitCount(value); i < c; i++)
7
      lcd_print_P(PSTR("0"));
8
  }
9
  lcd_print(str);
10
}
11
12
//-  Print string to cursor position
13
void lcd_print(char *string) {
14
15
  while(*string)  {
16
    lcd_putchar(*string++);
17
  }
18
}
19
//-  Put char to atctual cursor position
20
void lcd_putchar(char lcddata) {
21
22
  lcd_write((lcddata >> 4) | CMD_RS);
23
  lcd_write((lcddata & 0x0F) | CMD_RS);
24
}

Mein Aufruf:
1
#define IN2 !(PINA & (1<<PA6))//PIN34
2
#define JP1 !(PINA & (1<<PA0))//PIN39
3
#define JP2 !(PINA & (1<<PA1))//PIN40
4
5
lcd_printInt(JP1, 1, false);
6
lcd_printInt(JP2, 1, false);
7
lcd_printInt(IN2, 1, false);

Mein Workarround:
1
uint8_t combi = JP1*100+JP2*10+IN2;
2
lcd_printInt(combi, 3, true);

Grüße Oekel

von Felix U. (ubfx)


Bewertung
0 lesenswert
nicht lesenswert
D a v i d K. schrieb:
> char str[c];

also in c bytes kannst du schon mal nicht c Zeichen plus 1 Nullbyte für 
die Terminierung unterbringen. Vielleicht liegt es daran?

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Deine lcd_printInt hat einen Buffer Overflow bei
1
char str[c];


Der muss das ganze Ergebnis von utoa inklusive nachfolgender Null 
enthalten können.

von Kaj G. (Firma: RUB) (bloody)


Bewertung
0 lesenswert
nicht lesenswert
Du machst da ja auch ganz grossen Mist.
1
#define IN2 !(PINA & (1<<PA6))//PIN34
2
3
4
lcd_printInt(JP1, 1, false);  // <-- !!!
5
6
7
void lcd_printInt(uint16_t value, uint8_t c, bool leadingZeros) {
8
  char str[c];               // <-- !!!
9
  utoa(value, str, 10);      // <-- !!!
10
  if (leadingZeros) {
11
    ...
12
  }
13
  lcd_print(str);
14
}
15
16
17
void lcd_print(char *string) {
18
  while(*string)  {          // <-- !!!
19
    ...
20
  }
21
}

Schau dir mal die Stellen an, die ich markiert habe...
Dazu noch das hier:
http://www.atmel.com/webdoc/AVRLibcReferenceManual/group__avr__stdlib_1gad50d835af7e358518fd100179732e948.html
1
The function utoa() converts the unsigned integer value from val into
2
an ASCII representation that will be stored under s. The caller is
3
responsible for providing sufficient storage in s.
4
5
6
Note
7
8
The minimal size of the buffer s depends on the choice of radix. For
9
example, if the radix is 2 (binary), you need to supply a buffer with a
10
minimal length of 8 * sizeof (unsigned int) + 1 characters, i.e. one
11
character for each bit plus one for the string terminator. Using a larger
12
radix will require a smaller minimal buffer size.
13
14
15
Warning
16
17
If the buffer is too small, you risk a buffer overflow.

von zer0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
"Zeilenausgabe" - Hat das Ding Scrolling eingebaut oder sowas? Auf einem 
2-Zeilen display verschwindet die 3. sonst vermutlich im Nirvana.

Ansonsten: Die Timings für das Ding alle penibel beachtet? Sonst kann 
schon mal irgendetwas verschluckt werden - irgendwann...

Wenn der Code echt irgendwo hängen bleibt würde ich tippen, er wartet 
auf ein Zeichen vom LCD, das niemals kommt.

von Axel S. (a-za-z0-9)


Bewertung
-1 lesenswert
nicht lesenswert
Jim M. schrieb:
> Deine lcd_printInt hat einen Buffer Overflow bei
>
>
1
char str[c];
>
> Der muss das ganze Ergebnis von utoa inklusive nachfolgender Null
> enthalten können.

Nicht zu vergessen der Irrsinn, einen solchen Puffer überhaupt mit 
dynamischer(!) Länge anzulegen. Ein uint16_t hat maximal 5 
Dezimalstellen, dazu noch das terminierende \0, macht einen Buffer Länge 
6. Den alloziert man einmal, vorzugsweise als
1
static char str[6];

und nicht bei jedem Aufruf der Funktion wieder.

Mal wieder ein Traumbeispiel für den immer "korrekten Code" des TE.

von zer0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Felix U. schrieb:
> D a v i d K. schrieb:
>> char str[c];
>
> also in c bytes kannst du schon mal nicht c Zeichen plus 1 Nullbyte für
> die Terminierung unterbringen. Vielleicht liegt es daran?

Wenn man das so betrachtet klingt das plausibel. Allerdings - was sollte 
da denn auf dem Stack kaputt gehen, was 2 mal aber nicht 3 mal gut geht? 
Schreibt doch immer eine 0 also müsste alles deterministisch ablaufen...

von Stefan E. (sternst)


Bewertung
2 lesenswert
nicht lesenswert
zer0 schrieb:
> Allerdings - was sollte
> da denn auf dem Stack kaputt gehen, was 2 mal aber nicht 3 mal gut geht?

Die Return-Adresse.

von zer0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Stefan E. schrieb:
> zer0 schrieb:
>> Allerdings - was sollte
>> da denn auf dem Stack kaputt gehen, was 2 mal aber nicht 3 mal gut geht?
>
> Die Return-Adresse.

Und deshalb erscheint nichts auf dem Display?

von zer0 (Gast)


Bewertung
0 lesenswert
nicht lesenswert
zer0 schrieb:
> Stefan E. schrieb:
>> zer0 schrieb:
>>> Allerdings - was sollte
>>> da denn auf dem Stack kaputt gehen, was 2 mal aber nicht 3 mal gut geht?
>>
>> Die Return-Adresse.
>
> Und deshalb erscheint nichts auf dem Display?

Ach so, nach dem 2. ist er im Nirvana... Das könnte durchaus sein.

von D a v i d K. (oekel) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Axel S. schrieb:

> Mal wieder ein Traumbeispiel für den immer "korrekten Code" des TE.
Diese Aussage kreidest du mir wohl jetzt noch eine Weile an? :)

Ich bin nicht perfekt aber ebenso wenig nun eingeschnappt, daher gerne 
mehr davon, solange ich gleichzeitig viele hilfreiche Infos bekomme.

Nur SO lerne ich etwas. Danke.

von MaWin (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Vom Überlauf abgesehen wird der Code effizienter, wenn du den Puffer 
nicht dynamisch, sonder statisch auf dem Stack alloziierst. Als Größe 
einfach die Anzahl der Ziffern der größten Zahl, die utoa ausgeben kann, 
plus eins für NUL.

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]
  • [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.