Enkla men fatala buggar

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: Enkla men fatala buggar

Inlägg av superx »

blueint skrev:Samt "low = input & 0x0F << 4" till "low = (input & 0x0F) << 4" då är det illa! :vissla:
Ja, men det byter ju bara uttryckets betydelse. Det är definierat enligt standarden i båda fallen.
Användarvisningsbild
bit96
Inlägg: 2492
Blev medlem: 3 september 2007, 10:04:29
Ort: Säffle

Re: Enkla men fatala buggar

Inlägg av bit96 »

superx:
Ja det är definerat, men i praktiken är det som gjort för att skapa enkla men fatala buggar. :)

Alla vet att '2 + 3 * 4' är 14 (även om någon just nu fick det till 20 :) )
Jag skulle ändå ha skrivit '2 + (3 * 4)', alltså med parenteser.

Och det beror på att inom programmering måste allt stämma till 100,0000000000...%
Det finns inget utrymme för "nästan", "det borde", "men förra gången", "Nisse sa ju", "enligt Borland" eller ens "K&R skriver att".

I uttryck som

Kod: Markera allt

low = input & 0x0F << 4
kan jag garantera att det blir fel i mer än 0% av fallen, och då är det för mycket.

Vad händer om man kommer på att inporten har inverterade ingångar, och man slänger dit ett '!'.

Kod: Markera allt

low = !input & 0x0F << 4
Jag kan garantera att flera av er C-programmerare just nu sitter och funderar på prioritetsordning.
Och jag garanterar att ni i så fall har fel.

Problemet är inte bara prioritetsordningen, för att negera bit-vis används '~'. :)

Kod: Markera allt

low = ~input & 0x0F << 4
Och hur blir det med prioriteter nu? :)

Detta var ett exempel på 'normal' programmering, man ändrar, gör fel, lägger till, och testar desperat till slut nån obskyr lösning.
Se till att parenteser är med hela tiden. Då har man i alla fall eliminerat prioritets-fel.
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: Enkla men fatala buggar

Inlägg av superx »

Absolut! Klart man ska ha parenteser. Jag kommenterade bara påståendet att de behövs för att inte hamna i odefinierade fall.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Här finns en lista med prioritetsordningarna:
en.wikibooks.org/wiki/C_Programming/Reference_Tables#Table of Operators

Notera ordningen för:
~ bitwise not operator ~mask
<< left shift operator bits << shift_len
& bits & clear_mask_complement

Så uttrycket "low = input & 0x0F << 4" blir att 0x0F skiftas 4 steg först och sedan används bitmaskningen. Vilket i de flesta fall säkert inte avsågs..
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Detta forskningsresultat kan vara värt att kika igenom:
MIT: Towards Optimization-Safe Systems: Analyzing the Impact of Undefined Behavior

I stort så går det ut på att om din C-kod referar till pekare som är =NULL eller addition av pekare med signerade negativa heltal så kan kompilatorn plocka bort! delar av din kod. Ett exempel:
struct tun_struct *tun = ...;
struct sock *sk = tun->sk;
if (!tun)
return POLLERR; /* write to address based on tun */

For example, when gcc first sees the dereference tun->sk, it concludes that the pointer tun must be non-null, because the C standard states that dereferencing a null pointer is undefined [24:6.5.3]. Since tun is non-null, gcc further determines that the null pointer check is unnecessary and eliminates the check, making a privilege escalation exploit possible that would not otherwise be.
På sidan 4 i pdf:en så finns en tabell över optimeringar. Lathunden är att med GCC använda max -O1 för att undvika "oanade utfall..".
superx
Inlägg: 1127
Blev medlem: 19 juni 2012, 23:28:16
Ort: Linköping

Re: Enkla men fatala buggar

Inlägg av superx »

-O2 och -O3 innebär även att gcc gör ett antal antaganden (som är beskrivna i manualen). T.ex. får det inte finnas aliasing mellan pekare till olika typer. Det är upp till programmeraren att se till så att detta följs.
arte
Inlägg: 317
Blev medlem: 13 januari 2006, 01:18:50

Re: Enkla men fatala buggar

Inlägg av arte »

superx skrev:-O2 och -O3 innebär även att gcc gör ett antal antaganden (som är beskrivna i manualen). T.ex. får det inte finnas aliasing mellan pekare till olika typer. Det är upp till programmeraren att se till så att detta följs.
Intressant, skulle du kunna visa med ett kod exempel?
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Re: Enkla men fatala buggar

Inlägg av kimmen »

Sådan aliasing är ju inte heller tillåten enligt C-standarden, så det är med all rätt GCC gör sådana antaganden.

Här finns lite att läsa och kodexempel:
http://stackoverflow.com/questions/9865 ... asing-rule
Användarvisningsbild
Icecap
Inlägg: 26105
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Enkla men fatala buggar

Inlägg av Icecap »

Jag hade ett intressant exempel under veckan: Hade en rutin som kollade en delay-variabel. Plötsligt fungerade den inte, allting låste sig.

Och ja, jag vet att jag påstår att man ska undvika delay i program men ibland kan det behövas vid uppstart för att A/D nivåer ska stabilisera sig.

Nåväl, jag kollade lite och jag har ju en rutin med en 1ms interrupt som räknar ner delay-räknaren om den är icke-noll. Min "I'm alive!"-LED blinkade som den skulle (samma ISR) så det var ju OK.

Sedan kom jag på att GCC kan optimera ganska hårt och ger man inte de helt rätta direktiv kan man stänga av en del - så jag testade att deklarera delay-räknaren som volatile och det gjorde susen!
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Vad innebar volatile och hur deklareras den?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45168
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Enkla men fatala buggar

Inlägg av TomasL »

Volitile innebär att man förbjuder kompilatorn att ta bort det.
Kompilatorn kan få för sig att plocka bort kod och funktioner som den bedömer inte göra någon nytta. (i detta fallet en tidsfördröjning)
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Enkla men fatala buggar

Inlägg av sodjan »

Volatile betyder att kompilatorn inte ska göra några antaganden om variabels värde.
T.ex variablen "PORTA" i uC. Den kan ju ändra värde utan att det framgår av/i koden.
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Re: Enkla men fatala buggar

Inlägg av Micke_s »

En annan sak att veta om volatile, all skrivning och läsning kommer ske mot variablen/addressen och kompilatorn kan ej använda sina interna MCU register. Så det går lite långsammare av denna anledning.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Enkla men fatala buggar

Inlägg av blueint »

Cache kanske också ryker?
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 45168
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: Enkla men fatala buggar

Inlägg av TomasL »

Vad menar du?
Skriv svar