Enkla men fatala buggar
- JimmyAndersson
- Inlägg: 26308
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Re: Enkla men fatala buggar
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
variabel = !variabel (notera utropstecknet)
Alltså t.ex: true = inte true. Dvs false
Re: Enkla men fatala buggar
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
Hittade felet, stacken krockar med programminnet. kör allt i ram:et.
- JimmyAndersson
- Inlägg: 26308
- Blev medlem: 6 augusti 2005, 21:23:33
- Ort: Oskarshamn (En bit utanför)
- Kontakt:
Re: Enkla men fatala buggar
bit96 skrev:blueint: Ja, men nu glömde du att klamra in det som kommer efter "if()".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");
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
Om man anropar en funktion rekursivt för många gånger kan man få slut på stack utan någon vidare förvarning..
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..
Kod: Markera allt
func(int n){
printf("%d\n",n);
return func(n+1);
}
int main(){
func(0);
}
-
- Inlägg: 81
- Blev medlem: 13 april 2010, 14:40:04
- Ort: Stockholm
Re: Enkla men fatala buggar
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.
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
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.
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
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
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
Senast redigerad av blueint 5 juni 2013, 15:51:38, redigerad totalt 1 gång.
Anledning: urltrim
Anledning: urltrim
-
- Inlägg: 81
- Blev medlem: 13 april 2010, 14:40:04
- Ort: Stockholm
Re: Enkla men fatala buggar
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.
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
Och här kan/bör man t.ex. skriva nåt i stil med: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)) {}
Kod: Markera allt
string aaa;
int bbb;
if (int.TryParse(aaa, out bbb)) { /* Tomt här! Beräkning sker i själva if()-villkoret */}
Re: Enkla men fatala buggar
Eller bara strunta i IF-satsen helt och hållet:
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
Kod: Markera allt
string aaa;
int bbb;
int.TryParse(aaa, out bbb);
verkligen lyckas varje gång?
/johan
Re: Enkla men fatala buggar
Denna kodsnutt borde överlasta stacken utan alltför mycket varningar
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
Kod: Markera allt
int func(int n){
(void)printf("%d\n",n);
return func(n+1);
}
int main(void){
(void)func(0);
return 0;
}
@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
> 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...
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...
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
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
Kan man få till den icke optimerade varianten utan att mixtra kompilator optioner?