Forum: Mikrocontroller und Digitale Elektronik RST bei Buffernutzung


von Timo P (Gast)


Lesenswert?

Hallo!

ich bekomme immer einen RST, mehr kann mein code nicht...?!?
ATMEGA32 mit WINAVR, AVRStudio 4
1
#define BUFFER_SIZE 70  //buffergröße in Byte
2
volatile unsigned char buffer[BUFFER_SIZE] = "";
3
4
void kill_buffer()
5
{
6
  pread = 0;
7
  pwrite = 0;
8
  for(int ui1=0;ui1<BUFFER_SIZE;ui1++)
9
  {
10
    buffer[ui1]="";
11
    _delay_us(1000);
12
  }
13
}
14
15
int main()
16
{
17
  uart_puts("RST\r\n");
18
  kill_buffer();
19
}

von Karl H. (kbuchegg)


Lesenswert?

Bei aller Liebe.

Aber was ist jetzt die Frage?

von Timo P (Gast)


Lesenswert?

"" entspricht doch '\0' was einem C-String-Ende entspricht. warum kann 
ich das nicht auch an alle stellen schreiben?

von Bohrer (Gast)


Lesenswert?

Liegt am ungüstigen Variablennamen -> der Compiler optimiert die 
weiteren Durchläufe weg!

ändere "ui1" zb. zu "dhka"

von Floh (Gast)


Lesenswert?

Timo P schrieb:
> int main()
> {
>   uart_puts("RST\r\n");
>   kill_buffer();

  while(1)
    {
    }

> }

Da fehlt die abschließende Endlosschleife, da sonst das weitere 
Verhalten des uC nicht definiert ist (Reset, Programmneustart,...)

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> "" entspricht doch '\0' was einem C-String-Ende entspricht. warum kann

Nein das tut es nicht.
"" enstpricht an dieser Stelle der Startadresse eines leeren Strings, 
der irgendwo im Speicher liegt.

Strings kann man nicht einfach so zuweisen.


Die Frage ist aber eigentlich:
Was ist eigentlich genau deine Frage?

von Karl H. (kbuchegg)


Lesenswert?

Floh schrieb:
> Timo P schrieb:
>> int main()
>> {
>>   uart_puts("RST\r\n");
>>   kill_buffer();
>
>   while(1)
>     {
>     }
>
>> }
>
> Da fehlt die abschließende Endlosschleife, da sonst das weitere
> Verhalten des uC nicht definiert ist (Reset, Programmneustart,...)

Im Grunde hast du recht.
Allerdings schickt die gcc-Runtime nach einem return von main() den µC 
in eine Endlosschleife. So gesehen ist das Verhalten (beim gcc) 
definiert.

von Timo P (Gast)


Lesenswert?

meine Frage ist, warum ich einen Reset bekomme ab einer Buffergröße 
größer als 60

von Timo P (Gast)


Lesenswert?

ps:

mein main hat eine for(;;) schleife in der der UART-RX-buffer abgefragt 
wird

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> ps:
>
> mein main hat eine for(;;) schleife in der der UART-RX-buffer abgefragt
> wird

Dann zeig bitte das richtige Programm. OK?

von Floh (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Allerdings schickt die gcc-Runtime nach einem return von main() den µC
> in eine Endlosschleife. So gesehen ist das Verhalten (beim gcc)
> definiert.

Wieder was gelernt :-)

Timo P schrieb:
> mein main hat eine for(;;) schleife in der der UART-RX-buffer abgefragt
> wird

davon seh ich nichts im Programmausschnitt??

Wie wärs wenn du mal genau beschreibst, was du erreichen willst, und 
dann, was stattdessen passiert?

von Timo P (Gast)


Lesenswert?

ok....
1
int main( void )
2
{
3
  DDRA |= (1<<PIN);
4
  char s[22];
5
  unsigned char flag1,flag2,flag3,flag4;
6
    DDRC |= 0x01;
7
  PORTC |= 0x01;
8
  DDRB &= ~(1<<1);               // Conf. pin for recv. control signal 
9
  DDRD &= ~(1<<LIMIT_SWITCH_IN_PIN);  // Conf. pin for limit switch
10
  DDRD &= ~(1<<LIMIT_SWITCH_OUT_PIN);  // Conf. pin for limit switch
11
  DDRD |=  (1<<INSERT_PIN);        // Conf. pin for inserting "Falle"
12
  DDRD |=  (1<<RELEASE_PIN);        // Conf. pin for releasing "Falle"
13
    send = 0;
14
    _delay_ms(100);
15
    uart_init(BAUD);
16
  _delay_ms(100);
17
  strcpy(buffer, "");
18
    sei();
19
  uart_puts("RST\r\n");        // Reset of Hardware
20
  sprintf(s,"Buffersize:%d\r\n",BUFFER_SIZE);
21
  uart_puts(s);
22
  kill_buffer();
23
  
24
  unsigned char trigger = 0;
25
  unsigned char tmp = EEPReadByte(IS_CONFIGERD);
26
  //sprintf(s,"IS_CONFIGERD:%X\t\r\n",tmp);     // EEPROM-Wert von Adresse 0x20 lesen 
27
  //uart_puts(s);
28
29
    for(;;)
30
    {
31
    //if(RESET_PORT&(1<<RESET_PIN))EEPWriteByte(IS_CONFIGERD, 0x01);
32
    _delay_ms(10);
33
    sprintf(s,"<%s> \r",buffer);uart_puts(s);
34
35
    
36
     if(strstr(buffer,"\n"))    // command oder command-artiges erhalten
37
     {
38
       cli();
39
      if(strstr(buffer,"config:start\n"))  
40
        {
41
        kill_buffer();
42
        uart_puts("config:start:OK\n");
43
        sei();
44
45
      }
46
      else if(strstr(buffer,"config:end\n"))    // Request Pin switchen
47
        {
48
        kill_buffer();
49
        uart_puts("\t\t\t\tconfig:end:OK\n");
50
        EEPWriteByte(IS_CONFIGERD, 0x01);   // write Flag if configuration ist set
51
        sei();
52
      }      
53
       else if(strstr(buffer,"00T\n"))      // Anfrage Pin switchen
54
        {
55
        kill_buffer();
56
        PORTA ^= (1<<PIN);
57
//*****************************************************************************************************************
58
//PORTD ^= (1<<6);         // Insert "Falle"
59
//*****************************************************************************************************************
60
        if(trigger == 1)trigger = 0;
61
        if(trigger == 0)trigger = 1;
62
        uart_puts("00TOK\n");
63
        
64
      }
65
      else if(strstr(buffer,"00S\n"))      // Statusanfrage
66
        {
67
        kill_buffer();
68
        if(PORTA&(1<<PIN))uart_puts("00S1\n");
69
        if((PORTA&(1<<PIN)) == 0)uart_puts("00S0\n");
70
        
71
      }
72
      else if(strstr(buffer,"PING\n"))
73
        {  
74
        kill_buffer();
75
        uart_puts("PONG\n");      
76
      }
77
      else if(strstr(buffer,"set:ssid\t"))  // set:ssid\ta1b2c3d4\t\n
78
        {  
79
        int i = 9,j = 0;
80
        
81
        while(buffer[i] != '\t')
82
        {
83
          ssid[j] = buffer[i];
84
          i++;
85
          j++;
86
        }
87
        kill_buffer();
88
        sprintf(s,"<%s>",ssid);  uart_puts(s);
89
        uart_puts("set:ssid:OK\n");            
90
      }
91
      else if(strstr(buffer,"set:key\t"))  // set:ssid\ta1b2c3d4\t\n
92
        {  
93
        int i = 8,j = 0;
94
        
95
        while(buffer[i] != '\t')
96
        {
97
          key[j] = buffer[i];
98
          i++;
99
          j++;
100
        }
101
        kill_buffer();
102
        sprintf(s,"<%s>",key);  uart_puts(s);
103
        uart_puts("set:key:OK\n");            
104
      }
105
106
      else kill_buffer();
107
  
108
      sei();  
109
    } //if(strstr(buffer,"\n"))
110
111
112
113
114
115
//*****************************************************************************************************************
116
//* auskommentiert für manuelle Fallenkontrolle in eine Richtung, siehe oben PORT..^=...
117
//*****************************************************************************************************************
118
119
    if(trigger && open_signal == 0)
120
    {
121
      open_signal = 1;   // For remaining control signal
122
      uart_puts("open_signal =1\r\n");
123
      }
124
    if(open_signal && !flag1 && !flag2 && !flag3)
125
    {
126
      PORTD |= (1<<6);         // Insert "Falle"
127
      uart_puts("insert an D6\r\n");
128
      flag1 = 1;
129
    }  
130
    if(open_signal && flag1 && (PIND & (1<<5)))    // reaching limit switch
131
    {
132
      uart_puts("insert stop, release an D7\r\n");
133
      PORTD &= ~(1<<6);      // Einfahrt stoppen
134
      _delay_ms(100);
135
      PORTD |=  (1<<7);      // Ausfahrt starten
136
      flag2 = 1;
137
      flag1 = 0;
138
    }
139
140
    if(open_signal && (PIND & (1<<4)) && flag2)// reaching limit switch
141
    {
142
      PORTD &= ~(1<<RELEASE_PIN);
143
      flag1 = 0;
144
      flag2 = 0;
145
      open_signal = 0;
146
      uart_puts("release_pin aus, open_signal aus\r\n");
147
    }
148
149
150
//*****************************************************************************************************************
151
152
    } // for(;;)
153
154
  return(0);
155
}    // main()

von Timo P (Gast)


Lesenswert?

@ floh:

passiert:
Ständiger Reset! sehe ich an meiner RST\r\n Ausgabe

soll passieren:
µC resettet nicht in einer Tour, ohne überhaupt in meine foreverschleife 
zu gelangen...., da vor dem for(;;) der Code den µC zum Reset zwingt...

von Floh (Gast)


Lesenswert?

Ich sehe keine Interrupt-Routinen, warum aktivierst du über sei() die 
Interrupts?

von Karl H. (kbuchegg)


Lesenswert?

Dein Absturz wird höchst wahrscheinlich hier seinen Ursprung nehmen

    sprintf(s,"<%s> \r",buffer);uart_puts(s);

dein killBuffer hinterlässt nun mal in buffer keinen leeren String. 
Damit knallst du mit Sicherheit zuallererst einmal weit über die Grenzen 
von s drüber.

Das es mit Buffergrößen kleiner 60 scheinbar(*) funktioniert ist Zufall. 
Da erwischt du nur einfach nicht das richtige Byte um das komplette 
System zum Crashen zu bringen.

Um einen Buffer, der sowieso nur einen String aufnehmen kann zu löschen, 
vulgo den String auf einen Leerstring zu setzen, genügt es das erste 
Byte davon auf '\0' zu setzen. Man muss nicht durch das Array durchgehen 
und jedes einzelne Byte auf '\0' setzen.


(*) wie gesagt: scheinbar
Du hast trotzdem einen Fehler. Du siehst ihn nur nicht, weil du zufällig 
die falschen Bytes im Speicher zerstörst.

von Timo P (Gast)


Lesenswert?

weil ich die Interrupts nutzen möchte, aktiviere ich sie auch. Die ISR 
arbeitet wunderbar, wenn ich die Buffersize kleiner als 61 wähle!

Falls es interessiert hier die ISR für den uart-empfang:

ISR (USART_RXC_vect)
{
  buffer[pwrite]=UDR;
  pwrite++;
  if(pwrite >= BUFFER_SIZE) pwrite=0;
}

von Timo P (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Um einen Buffer, der sowieso nur einen String aufnehmen kann zu löschen,
> vulgo den String auf einen Leerstring zu setzen, genügt es das erste
> Byte davon auf '\0' zu setzen. Man muss nicht durch das Array durchgehen
> und jedes einzelne Byte auf '\0' setzen.

ich überprüfe, ob ich ein config:start\n empfangen habe. dazu nutze ich 
strstr(). Wenn ich aber nun den Buffer nur an [0] auf '\0' setze, sind 
die anderen Zeichen nicht automatisch weg oder?

Oder sucht die Funktion strstr() nur bis zum \0 Zeichen?
Dann wäre das eine Lösung, mit kill_buffer nur die erste Stelle auf das 
Stringendezeichen zu setzen...

THX für weitere antwort

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> Karl heinz Buchegger schrieb:
>> Um einen Buffer, der sowieso nur einen String aufnehmen kann zu löschen,
>> vulgo den String auf einen Leerstring zu setzen, genügt es das erste
>> Byte davon auf '\0' zu setzen. Man muss nicht durch das Array durchgehen
>> und jedes einzelne Byte auf '\0' setzen.
>
> ich überprüfe, ob ich ein config:start\n empfangen habe. dazu nutze ich
> strstr(). Wenn ich aber nun den Buffer nur an [0] auf '\0' setze, sind
> die anderen Zeichen nicht automatisch weg oder?

Richtig - Sind sie nicht.
Aber wen kümmerts?

Ein String ist mit dem ersten '\0' Zeichen zu Ende. Was dann noch 
dahinter kommt interessiert keinen. Auch die str... Funktionen wissen 
das und halten sich daran. So sind Strings in C nun mal definiert.

> Oder sucht die Funktion strstr() nur bis zum \0 Zeichen?

An dieser Stelle ist dann der Hinweis auf ein C-Buch angebracht

> Dann wäre das eine Lösung, mit kill_buffer nur die erste Stelle auf das
> Stringendezeichen zu setzen...

Und mach dein s größer!
Wenn im Extremfall dein Buffer voll ist, dann ist da ein String der 
Länge 70 drinnen. Der wird aber kaum in s (mit 22 Zeichen) reinpassen!

von Timo P (Gast)


Lesenswert?

ok, s ist vergrößert.
ich habe nun in der kill_buffer() nur noch buffer[0] = '\0' gesetzt.

Nun empfange ich nur noch Müll! wenn ich per Terminalprogramm Zeichen 
eintippe, empfange ich sie nur noch einzeln wenn ich mal ein \n drin 
hatte....

von Karl H. (kbuchegg)


Lesenswert?

Oh Himmel
1
      while(buffer[i] != '\t')
2
        {
3
          ssid[j] = buffer[i];
4
          i++;
5
          j++;
6
        }
7
        kill_buffer();
8
        sprintf(s,"<%s>",ssid);  uart_puts(s);

Da fehlts ja an allen Ecken und Enden in der Stringverarbeitung

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> ok, s ist vergrößert.
> ich habe nun in der kill_buffer() nur noch buffer[0] = '\0' gesetzt.
>
> Nun empfange ich nur noch Müll!

Aber du hast keinen Absturz mehr.

Also: -> nächsten Fehler suchen! UNd du hast noch viele im Programm.

von Timo P (Gast)


Lesenswert?

mein Programm hat ja mal gelaufen, als die Buffer kleiner waren!
Ich konnte z.B. erfolgreich eine ssid, die übergeben wurde, 
interpretieren.

denken kann ich mir aber, dass hier gemeint ist, dass ich die 
string-token funktion nutzen soll...

Wo hab ich denn noch Fehler?

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:

> ISR (USART_RXC_vect)
> {
>   buffer[pwrite]=UDR;
>   pwrite++;
>   if(pwrite >= BUFFER_SIZE) pwrite=0;
> }

Das ist deine Empfangsfunktion?

Dann kannst du das hier
1
    for(;;)
2
    {
3
    //if(RESET_PORT&(1<<RESET_PIN))EEPWriteByte(IS_CONFIGERD, 0x01);
4
    _delay_ms(10);
5
    sprintf(s,"<%s> \r",buffer);uart_puts(s);

nicht machen. In buffer ist zu diesem Zeitpunkt kein gültiger String.

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> mein Programm hat ja mal gelaufen, als die Buffer kleiner waren!

Dein Programm hat höchstens zufällig keinen Absturz produziert.
Korrekt gelaufen ist das nie. Zumindest nicht solange, solange du keine 
korrekt terminierten Strings hast.

von Timo P (Gast)


Lesenswert?

die kommands, die ich übermittelt bekomme, werden durch ein \n 
terminiert.

die ausgabe ..<%s>\r... in der for(;;) ist nur zu debugzwecken gedacht.

von Ago (Gast)


Lesenswert?

Timo P schrieb:
> {
...
>         if(trigger == 1)trigger = 0;
>         if(trigger == 0)trigger = 1;
>         uart_puts("00TOK\n");

Ähm.. ist das so gewollt, das trigger nicht 0 werden kann?

Oder wolltest du vielleicht schreiben

if (trigger == 1) then
  trigger == 0;
else
  trigger == 1;

Oder, kurzform:
trigger = (trigger) ? 0 : 1;

von Karl H. (kbuchegg)


Lesenswert?

Als Quick-Fix ändere das mal
1
ISR (USART_RXC_vect)
2
{
3
  buffer[pwrite]=UDR;
4
5
  pwrite++;
6
  if(pwrite >= BUFFER_SIZE)
7
    pwrite=0;
8
9
  buffer[pwrite] = '\0';
10
}

damit hast du zumindest im Input-Buffer ständig einen insofern gültigen 
C-String, als das er nach dem zuletzt empfangenen Zeichen 0-terminiert 
ist.

von Timo P (Gast)


Lesenswert?

DANKE!
Genau das war mein Fehler, falls ich in der kill_buffer() Fkt. 
ausschließlich buffer[0]= '\0' setzen wollte..

von Ago (Gast)


Lesenswert?

Hallo,

Karl heinz Buchegger schrieb:
> damit hast du zumindest im Input-Buffer ständig einen insofern gültigen
> C-String, als das er nach dem zuletzt empfangenen Zeichen 0-terminiert
> ist.

hat er nicht (glaube ich... ;-)

Wenn USART_RXC_vect hier wieder das erste Zeichen des Buffers mit einem 
gültigen Zeichen überschreibt, sieht jede String-Funktion in C wieder 
den gesamten Buffer, plus das was dahinter im Speicher folgt (wenn nicht 
irgendwo im Buffer wieder ein /0 steht).

Wenn man es schon so machen muß wie der TE dann vllt. so:

#define BUFFER_SIZE 70  //buffergröße in Byte
volatile unsigned char buffer[1 + BUFFER_SIZE];
...
buffer[BUFFER_SIZE] == 0;

Damit wäre der Buffer immer NULL-Terminiert.

von Ago (Gast)


Lesenswert?

Argh ich nehm das zurück.. hat er doch, hab nicht aufgepasst. Sorry :)

von Timo P (Gast)


Lesenswert?

hab ich wohl, denn, wenn der RX-Interrupt das erste Zeichen 
überschreibt, hängt er automatisch ein '\0' an dank shiften des writer 
pointers um genu diese Bitbreite, die die Bufferelemente auch 
besitzen.....

so läuft es perfekt!

von Karl H. (kbuchegg)


Lesenswert?

Ago hat sich ins Boxhorn jagen lassen durch deine Variablen und der 
Tatsache dass du den Index am Ende des Buffers wieder auf 0 setzt. Er 
dachte das wäre ein Ringbuffer. Das ist er aber nicht. Sieht nur auf den 
ersten Blick so aus.

von Karl H. (kbuchegg)


Lesenswert?

Ago schrieb:

> Ähm.. ist das so gewollt, das trigger nicht 0 werden kann?
>
> Oder wolltest du vielleicht schreiben
>
> if (trigger == 1) then
>   trigger == 0;
> else
>   trigger == 1;

mit dem else hat ers nicht so

       if(PORTA&(1<<PIN))uart_puts("00S1\n");
        if((PORTA&(1<<PIN)) == 0)uart_puts("00S0\n");

von Karl H. (kbuchegg)


Lesenswert?

Was passiert eigentlich, wenn der Benutzer
1
      else if(strstr(buffer,"set:ssid\t"))  // set:ssid\ta1b2c3d4\t\n
2
        {  
3
        int i = 9,j = 0;
4
        
5
        while(buffer[i] != '\t')
6
        {
7
          ssid[j] = buffer[i];
8
          i++;
9
          j++;
10
        }

auf den Tab bei der Eingabe vergisst?

von Karl H. (kbuchegg)


Lesenswert?

Dir ist auch klar, dass der Eingabetext

reset::ssid\t

(für \t drück ich natürlich den Tabulator)

auf diese Abfrage
1
     else if(strstr(buffer,"set:ssid\t"))
passt?

strncmp eignet sich für solche Auswertungen besser als strstr
1
   else if( strncmp( buffer, "set::ssid\t", 10 ) == 0 )
jetzt muss der String mit "set::ssid\t" anfangen, nur dann gilt der Text 
als erkannt. reset::ssid\t passt jetzt nicht mehr.

Vielleicht hängt ja am anderen Ende der Leitung kein Mensch, aber die 
Sache mit dem \t würde ich mir insgesammt nochmal überlegen. Es sei denn 
natürlich, das da ein anderes Programm deinen µC füttert und dort ist 
das schon so festgelegt.

von Peter (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Was passiert eigentlich, wenn der Benutzer
> auf den Tab bei der Eingabe vergisst?

dann wird der Ram umsortiert...

von Timo P (Gast)


Lesenswert?

aus if...if ist längst ein if else geworden.

Mir ist auch bewusst, dass ich ein Bit aus einem 8-Bit char einzeln 
toggeln könnte.

Dann müsste ich aber wieder die Bitmasken nutzen, sowohl bei der 
Zuweisung, als auch bei der Abfrage des Flags...

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> aus if...if ist längst ein if else geworden.
>
> Mir ist auch bewusst, dass ich ein Bit aus einem 8-Bit char einzeln
> toggeln könnte.

Eine Schreibweise, die mir persönlich gut gefällt

   trigger = 1 - trigger;

keine Ahnung warum, aber ich finde das hat was :-)

> Dann müsste ich aber wieder die Bitmasken nutzen, sowohl bei der
> Zuweisung, als auch bei der Abfrage des Flags...

na, na

    trigger ^= 0x01;

so schlimm ist das auch wieder nicht.
Besser als
        if(trigger == 1)trigger = 0;
        else if(trigger == 0)trigger = 1;
ist es allemal.

von Timo P (Gast)


Lesenswert?

dann frage ich aber auch das "0-te" Bit ab.... Dann gehts....

Oder ich hab mal was von Bitmasken gesehen, ein Strukt, in dem 8 Bits 
sind. Diese kann ich dann über ein define nutzen, quasi ein eigenes sbit 
für die AVRs, die ja keine bitadressierung haben.....

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> dann frage ich aber auch das "0-te" Bit ab.... Dann gehts....

kannst du natürlich machen.
Aber bei all den Alternativvorschlägen ging es bisher immer nur darum, 
trigger zwischen 0 und 1 hin und her wechseln zu lassen. Das machen alle 
bisher hervorgebrachten Alternativen. Manche der Alternativen haben noch 
einen zuätzlichen Nebeneffekt bzw. zusätzliche Eigenschaften, der/die 
hier bei dir nicht zum tragen kommt, da trigger offenbar sowieso nur 0 
und 1 sein kann und auch das auch so sein soll.

von Timo P (Gast)


Lesenswert?

Hier habe ich genug speicher und nutze ein komplettes byte als flag aus.
Missbrauch?!? ok, soll jeder so sehen, wie er es möchte.

Im übrigen sind alle commands, die hier zum tragen kommen, von einer GUI 
am PC über USB zum µC übertragen.

Daraus erzeuge ich dann andere Commands, die ich an ein WLAN-Modul 
übertrage.

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> Hier habe ich genug speicher und nutze ein komplettes byte als flag aus.
> Missbrauch?!? ok, soll jeder so sehen, wie er es möchte.

Darum gehts nicht.

Das hier
1
    if(trigger == 1)trigger = 0;
2
    else if(trigger == 0)trigger = 1;
ist für deinen µC so ziemlich die aufwändigste Methode, das Gewünschte 
zu erreichen.

>
> Im übrigen sind alle commands, die hier zum tragen kommen, von einer GUI
> am PC über USB zum µC übertragen.

ok. nehm ich zur Kentniss. Also musst du nicht besondere Sorgfalt in der 
Auswertung walten lassen. Du kannst davon ausgehen, dass der String 
immer vollständig und wohl geformt ist (abgesehen von 
Übertragungsfehlern natürlich)

von Timo P (Gast)


Lesenswert?

ist gemeint, dass die Übertragungsfehler mindestens mit genau der selben 
Entgegnung/Auswertung optimiert werden sollen, wie Fehleingaben?

Oder hieß das, dass ich drauf vertrauen könnte? Wenn die GUI mir

set:ssid\thier_die_ssid\t\n

sendet, ich aber nicht mit einem

set:ssid:OK\n

antworte, weiß die Gui, dass sie erneut senden muss. Selbstverständlich 
versucht sie es nicht hunderte mal....

von Peter (Gast)


Lesenswert?

Timo P schrieb:
> ist gemeint, dass die Übertragungsfehler mindestens mit genau der selben
> Entgegnung/Auswertung optimiert werden sollen, wie Fehleingaben?

nein, das nicht. Aber dein Programm macht nach den vergessenen tab 
nichts mehr sinnvollens. Du musst also den µC neu starten.

von Timo P (Gast)


Lesenswert?

Das ist doch mal nen Argument...

strstr hätte den vorteil:

&$?=config:start\n wird von mir auch interpretiert, falls sich diese 
Zeichen vor config:start\n einschleichen sollten.

das strncmp klingt auch gut. (Welcher Vorteil ergibt sich praktisch 
durch das n, also die Angabe der Anzahl der zu prüfenden zeichen?)

von Timo P (Gast)


Lesenswert?

für die \t\t fehlerabfrage würde ich eine mindestgröße von sagen wir 1 
zeichen festlgegen, bei der mein code ein ...OK zurücksendet und die 
Daten in das entsprechende array schreibt.

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:
> Das ist doch mal nen Argument...
>
> strstr hätte den vorteil:
>
> &$?=config:start\n wird von mir auch interpretiert, falls sich diese
> Zeichen vor config:start\n einschleichen sollten.

die Frage ist ob du das überhaupt willst.
Falls sich da vor config::start\n ein paar Zeichen eingeschlichen haben, 
die da eigentlich nicht hingehören, woher willst du dann wissen, dass 
dieses config::start nicht eigentlich auch fehlerhaft ist und eigentlich 
gar nicht da hingehört?

> das strncmp klingt auch gut. (Welcher Vorteil ergibt sich praktisch
> durch das n, also die Angabe der Anzahl der zu prüfenden zeichen?)

Ich muss meinen String nicht in Einzelteile zerlegen
Dieser strncmp ist das Equivalent zu: Wenn die ersten n Buchstaben 
(sofern es überhaupt n gibt) diesen Text hier bilden, dann ist alles 
gut.

von Timo P (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> dann ist alles
> gut.

klingt doch super ;)

nein im Ernst, Danke für die Anregungen zu meinem code. Sicher, man kann 
leute auf ein C-Buch verweisen. Aber irgendwie schreibt man dann doch 
auch mal mist zusammen. Sehen wir ja hier. Danke für eure Anregungen, 
nur so kann ich mich ja verbessern!

Weiter so im Forum!

von Karl H. (kbuchegg)


Lesenswert?

Timo P schrieb:

> auch mal mist zusammen. Sehen wir ja hier. Danke für eure Anregungen,
> nur so kann ich mich ja verbessern!

Das allerwichtigste bei der Arbeit mit Strings in C:

Du musst dir bei jeder Aktion immer im klaren sein, dass es kein 
Fangnetz gibt. Wenn du, aus welchem Grund auch immer, versuchst 20 
Zeichen in ein char-Array der Länge 10 zu quetschen, dann wird das 
grauslich schief gehen. Nicht nur das, es werden unter Umständen 
seltsame Phenomäne in deinem Programm auftauchen, Dinge die bisher schon 
funktioniert haben werden plötzlich nicht mehr funktionieren, 
Berechnungen liefern falsche Ergebnisse, Funktionsreturns landen 
plötzlich nicht mehr an der Stelle an der die Funktion aufgerufen wurde 
etc.

Daher: Bei jeglicher Stringaktion lieber konservativ arbeiten. Was kann 
schief gehen? Wenn du den String von einem Benutzer hast: Nicht darauf 
verlassen, dass der alles richtig eingibt. Wenn Strings über eine 
Leitung übertragen werden: Auch wenn es mitlerweile selten vorkommt, 
aber es gibt sie noch, die Übertragungsfehler.

Das mindeste, was man immer tun sollte, so lange man im Programm nicht 
sicher gestellt hat, das der String nicht zu lang sein kann:
Wenn man einen String (oder Teilstring) in ein anderes Array umkopiert, 
immer die Länge des Zielarrays im Auge behalten und notfalls das 
Umkopieren abwürgen, wenn man das Ziel überläuft!

Nicht wenige der frühen Hacker-Angriffe auf andere Rechner sind genau 
über solche Schlupflöcher gelaufen: Man hat ins Programm einen sehr 
langen String eingespielt, weil man genau wusste das dort und dort in 
der Umkopierschleife keine Sicherung gegen Überlaufen enthalten ist. 
Damit hat das Programm selber den Schadcode an die richtige Stelle im 
Speicher kopiert und das Tor aufgemacht.

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.