[Glaskugel] Funktionsaufruf lässt Controller hängen

OP Persönliche Seite #5101925
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
(Firma: RUB) #5101937
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.
Gast #5101947
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.
#5101950
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.
Gast #5101955
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...
Gast #5101966
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.
Gast #5101984
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

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