Sida 7 av 11

Re: Enkla men fatala buggar

Postat: 9 oktober 2013, 09:27:21
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.

Re: Enkla men fatala buggar

Postat: 9 oktober 2013, 09:46:29
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.

Re: Enkla men fatala buggar

Postat: 9 oktober 2013, 09:50:14
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.

Re: Enkla men fatala buggar

Postat: 9 oktober 2013, 10:03:54
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..

Re: Enkla men fatala buggar

Postat: 30 oktober 2013, 01:48:11
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..".

Re: Enkla men fatala buggar

Postat: 30 oktober 2013, 07:52:18
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.

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 05:56:06
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?

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 16:03:37
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

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 16:24:19
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!

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 16:56:13
av blueint
Vad innebar volatile och hur deklareras den?

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 17:16:04
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)

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 17:23:00
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.

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 18:15:33
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.

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 18:32:23
av blueint
Cache kanske också ryker?

Re: Enkla men fatala buggar

Postat: 1 juni 2014, 19:34:24
av TomasL
Vad menar du?