Sida 3 av 11
Re: Enkla men fatala buggar
Postat: 27 maj 2013, 07:46:03
av Micke_s
Något är lustigt i alla fall i görningen.
Re: Enkla men fatala buggar
Postat: 31 maj 2013, 14:43:21
av JimmyAndersson
Ingen bugg, men ett trick för att toggla (invertera) en logisk (boolsk) variabel:
variabel = !variabel (notera utropstecknet)
Alltså t.ex: true = inte true. Dvs false
Re: Enkla men fatala buggar
Postat: 31 maj 2013, 15:57:19
av blueint
Och ett sätt at konvertera t.ex 5 till 0 eller 0 till 1 .. helst utan att man tänker på det

Re: Enkla men fatala buggar
Postat: 1 juni 2013, 10:01:14
av Micke_s
Hittade felet, stacken krockar med programminnet. kör allt i ram:et.
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 03:00:48
av JimmyAndersson
bit96 skrev:
blueint skrev:Så här kan man också göra:
Kod: Markera allt
unsigned char ch;
if( ch == 0x81 )
printf("Seems it's an unsigned day today ;-)\n");
blueint: Ja, men nu glömde du att klamra in det som kommer efter "if()".
Inte nödvändigt, men rekommenderat för att undvika fatala buggar.

Apropå det så finns det ju fall där det faktiskt inte behöver vara något mellan klamrarna.
Ett exempel för att omvandla string till int hyfsat felsäkert:
string aaa;
int bbb;
if (int.TryParse(aaa, out bbb)) {}
Om aaa är siffror i en sträng så hamnar siffrorna i bbb. Inte annars.
Nu har man inte så nytta av själva exemplet i µC-sammanhang,
men det visar att man bör funderar lite extra över sina if-satser.
Vissa miljöer hanterar dessutom
=> på ett annat sätt än
>=.

Re: Enkla men fatala buggar
Postat: 5 juni 2013, 05:11:21
av blueint
Om man anropar en funktion rekursivt för många gånger kan man få slut på stack utan någon vidare förvarning..
Kod: Markera allt
func(int n){
printf("%d\n",n);
return func(n+1);
}
int main(){
func(0);
}
Test på x86 fbsd+gcc gav 2 096 966 rekursioner, dito på SunOS 5 gav 74 852 rekursioner. En viss Borland kan stanna vid cirka 8000..
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 08:06:00
av jappelino_1
liknande situation med en ganska lång diskussion som jag "förlorade":
http://msp430-discuss.996251.n3.nabble. ... tml#a26857
Det som jag tycker är lite konstigt är att kompilatorn var satt till att inte optimera koden men ändå gjorde det.
Jag tror jag löste det med några fula globala variabler istället.
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 08:49:03
av sodjan
Blueints kod ger (förrutom en stack-overflow så klart vid runtime) en del andra varningar.
OK, det kanske var förväntat och enbart om man slår på lite extra kontroller...

Jag fick även lägga till en include av stdio.
För övrigt smällde det av vid ca 2.3 M varv, men det är ju enbart en funktion av
storleken på stacken så det är ganska ointressant och det är kanske lite tveksamt
hur mycket det beror på de olika plattformarna/kompilatorerna att göra.
Kod: Markera allt
$ cc rekurs/warn=(enab=level6,verbose)
func(int n){
^
%CC-I-DEFRETURNTYPE, The type of the function func defaults to "int".
at line number 2 in file USER:[JANNE]REKURS.C;2
Description: A function definition did not include a type specifier for the function's return value.
It will default to int. This might not be what you intend. This is also a violation of the C99 Standard.
User Action: It is a good programming practice to give all function definitions explicit return types.
printf("%d\n",n);
^
%CC-I-IGNORECALLVAL, In this statement, the value returned from the function "printf(...)" is not used
- if this is intended, it should be cast to "void".
at line number 3 in file USER:[JANNE]REKURS.C;2
Description: A function that returns a value has been invoked, yet the value was not used.
This might not have been what you intended.
User Action: Cast the function to void to suppress the message.
int main(){
....^
%CC-I-NOPARMLIST, The declaration of the function main has an empty parameter list.
If the function has parameters, they should be declared here; if it has no parameters,
"void" should be specified in the parameter list.
at line number 7 in file USER:[JANNE]REKURS.C;2
Description: The recommended way to declare a function that takes no parameters is to use "void" in the parameter list.
User Action: Make the recommended change.
func(0);
^
%CC-I-IGNORECALLVAL, In this statement, the value returned from the function "func(...)" is not used
- if this is intended, it should be cast to "void".
at line number 8 in file USER:[JANNE]REKURS.C;2
Description: A function that returns a value has been invoked, yet the value was not used.
This might not have been what you intended.
User Action: Cast the function to void to suppress the message.
$
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 09:18:17
av johano
Vill bara tipsa om en bok som jag tyckte var rätt bra när jag läste den för ca. 20 år sen: "Writing Solid Code - Microsoft's Techniques for Developing Bug-Free C Programs" av Steve Maguire.
Det verkar finnas en online pdf-version här, vet inte lagligheten i den länken dock:
vmg.pp.ua/books/../Microsoft/Microsoft Press - Writing Solid Code.pdf
/johan
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 12:22:43
av jappelino_1
Ett till boktips:
Han har fått mycket bra recensioner, själv har jag bara kommit in en bit i boken, men så långt verkar det lovande.
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 14:05:25
av bit96
JimmyAndersson skrev:
Apropå det så finns det ju fall där det faktiskt inte behöver vara något mellan klamrarna.
Ett exempel för att omvandla string till int hyfsat felsäkert:
string aaa;
int bbb;
if (int.TryParse(aaa, out bbb)) {}
Och här kan/bör man t.ex. skriva nåt i stil med:
Kod: Markera allt
string aaa;
int bbb;
if (int.TryParse(aaa, out bbb)) { /* Tomt här! Beräkning sker i själva if()-villkoret */}
Annars har man efter några månader helt glömt varför man har ett par tomma klamrar här.

Re: Enkla men fatala buggar
Postat: 5 juni 2013, 14:15:04
av johano
Eller bara strunta i IF-satsen helt och hållet:
Kod: Markera allt
string aaa;
int bbb;
int.TryParse(aaa, out bbb);
Men, då tråden handlar om buggar så kommer ju frågan om man kan vara säker på att konverteringen
verkligen lyckas varje gång?
/johan
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 15:55:05
av blueint
Denna kodsnutt borde överlasta stacken utan alltför mycket varningar
Kod: Markera allt
int func(int n){
(void)printf("%d\n",n);
return func(n+1);
}
int main(void){
(void)func(0);
return 0;
}
Att missa deklerationen av funktionens returvärde kan nog också ses som fatalt om man inte ser upp. Det övriga är av ringa betydelse.
@johano, Alltså vet man inte..

antingen får man köra if() och göra något åt det. Eller senare kontrollera indatat. Alternativt shit-happens

Re: Enkla men fatala buggar
Postat: 5 juni 2013, 17:30:59
av sodjan
> Denna kodsnutt borde överlasta stacken utan alltför mycket varningar
Det kompilerade och länkade utan diagnostiska meddelanden...

Däremot vet i fanken varför det aldrig stannar. Räknaren slår runt
och det bara fortsätter...
Aha!

Det visade sig att funktionen optimerades till inline kod utan några CALL's
(förrutom till printf) och stacken kraschade så klar aldrig:
> 1. Inlining func into main
Det blev bara *8* maskininstruktioner kvar (plus lite init och exit kod som aldrig körs) av det hela.
Ja, printf koden körs ju också så klart...
Kod: Markera allt
0030 L$2:
A7420020 0030 LDQ R26, 32(R2)
47E30411 0034 MOV n, R17 ; R3, R17
47E05419 0038 MOV 2, R25
22020030 003C LDA R16, 48(R2)
A7620028 0040 LDQ R27, 40(R2)
40603003 0044 ADDL n, 1, n ; R3, 1, R3
6B5A4000 0048 JSR R26, DECC$GXPRINTF ; R26, R26
C3FFFFF8 004C BR L$2
Med /NOOPTIMIZE så kraschade det med en ACCVIO (Access Violation, d.v.s
normalt en skrivning till read-only minnesområde) efter ca 1.5 M varv...

Efter att ha ökat virtuella minnet för usern så gick det ca 15.5 M varv.
Processen växer dynamiskt när det behövs mera (t.ex) stack tills det slår i taket...
Re: Enkla men fatala buggar
Postat: 5 juni 2013, 17:38:44
av blueint
Kan man få till den icke optimerade varianten utan att mixtra kompilator optioner?