"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs
of natuurlijk "poor man's debugging" met schrijven naar de std out
(het hangt natuurlijk voor een groot gedeelte van de taal waarin je werkt af)
Ikzelf gebruik vaak beiden.
"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs
ten eerste heb je echt pagina's aan output in een routine die 100.000 keer aangeroepen wordt (okee beetje overdreven, maar het gaat om het idee), en ten 2e zeggen al die getalletjes je zo niets
hoe ik het aanpak: je moet je bug zien te isoleren. Met puur gebruik maken van breakpoints en door je code heen steppen heb je meestal niets als het sporadisch voorkomt. Dus moet je je bug kunnen reproduceren, zodat je precies weet wanneer hij optreedt. Dus dan maak je een soort van wrapper om je bug heen, die ervoor zorgt dat de bug direct optreedt
dan kan je door je code heen steppen, maar mischien handiger is om te isoleren door delen van je code te commenten of te wijzigen (mits dat mogelijk is natuurlijk; het moet wel blijven werken). Dan ben je op een gegeven moment bij je stukje code waar hij optreedt en dan kijk je waarom ie optreedt (door de variabelen te controleren). 99 van de 100 keer treedt ie daar op omdat het een stukje terug al fout is gegaan, dus dan ga je backtracken (hoe kom je aan die waarden van de variabelen)
Maar ik denk dat het ook nogal afhangt van wat voor soort stuk code het is waar je bug optreedt.
En dan is er nog de Heisenbug, practisch ondetecteerbaar. Ben je wel een tijdje zoet mee als je zoiets hebt
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Ah, ff opgezocht op google.. die heb ik op m'n stage gehad, na 4 weken nog niks gevonden
Momenteel probeer ik een DCOM client server programma te debuggen, maar ik heb een beetje het idee dat de "conventionele" debug methoden (breaks + stappen) niet echt goed van toepassing zijn...
Zo heb ik nu het probleem dat ik eerst in een functie zit, dan is ie halverwege, als ik vervolgens weer een trace doe zit ik opeens in een geheel andere functie
Maar ik heb dus in dit geval het idee dat ik gewoon met de normale methoden geen steek verder kom. (kan aan mij liggen hoor)
"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs
Anoniem: 39126
cout << variabele (zoals ik toch wel vaak doe
even voor de mensen die niet zo goed kunnen googlen als jij ;):Op zondag 16 juni 2002 00:23 schreef _Mo_ het volgende:
De heisenbug?
Ah, ff opgezocht op google.. die heb ik op m'n stage gehad, na 4 weken nog niks gevondenDie is inderdaad niet zo heel erg fijn..
de heisenbug is een bug die maar soms optreedt. De ene keer wel, de andere keer niet, terwijl de omstandigheden hetzelfde blijven (dus bijvoorbeeld de ene keer start je programma goed op, terwijl hij een andere keer crasht)
En het leuke is, door het gebruik van een debugger kan het ook nog eens zo zijn dat de bug dus niet optreedt, dus zul je m ook niet vinden
99.999% komt het gewoon door gebruik van ongeinitialiseerd stukje geheugen. Aangezien de waarden daarvan elke keer weer anders kan zijn treedt ie dus niet altijd op. En een debugger geheugen initializeert geheugen meestal met een bepaalde waarde, dus kan het ook zo zijn dat ie dan juist niet optreedt
bron: http://info.astrian.net/jargon/terms/h/heisenbug.htmlheisenbug /hi:'zen-buhg/ n. [from Heisenberg's Uncertainty Principle in quantum physics] A bug that disappears or alters its behavior when one attempts to probe or isolate it. (This usage is not even particularly fanciful; the use of a debugger sometimes alters a program's operating environment significantly enough that buggy code, such as that which relies on the values of uninitialized memory, behaves quite differently.) Antonym of Bohr bug; see also mandelbug, schroedinbug. In C, nine out of ten heisenbugs result from uninitialized auto variables, fandango on core phenomena (esp. lossage related to corruption of the malloc arena) or errors that smash the stack.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Bij het binnengaan en buitengaan van elke functie wordt er in je output file in of uitgesprongen.
In de inspringingen staat dan de debugmessages, erg handig
Voorbeeldje :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
| Sims 0.1 - DEBUG FILE ===================== Logging started : zondag 16 juni 2002 0:24:21 (002421) [[[ SIMS [[[ (002421) ~~~[[[ Splash_tmrDBG_Timer::DBG LOAD SUCCESS [[[ (002421) ~~~~~~~~~~DBG LOAD OK (002421) ~~~~~]]] Splash_tmrDBG_Timer::DBG LOAD SUCCESS ]]] (002421) ~~~[[[ Splash_tmrCFG_Timer [[[ (002421) ~~~~~~~~~~CFG_Load :: fail :: FALSE (002421) ~~~~~~~~~~CFG LOAD OK (002421) ~~~~~]]] Splash_tmrCFG_Timer ]]] (002421) ~~~[[[ Splash_tmrDBS_Timer [[[ (002421) ~~~~~~~~~~DBS LOAD OK (002421) ~~~~~]]] Splash_tmrDBS_Timer ]]] (002422) ~~~[[[ Splash_tmrALL_Timer [[[ (002422) ~~~~~[[[ doUpdate [[[ (002422) ~~~~~~~~~~]]] doUpdate ]]] (002422) ~~~~~]]] Splash_tmrALL_Timer* ]]] (002422) ~~~[[[ Splash_tmrALL_Timer [[[ (002422) ~~~~~[[[ doUpdate [[[ (002422) ~~~~~~~~~~]]] doUpdate ]]] (002422) ~~~~~~~~~~Unload splash... (002422) ~~~~~[[[ doUpdate [[[ (002422) ~~~~~~~~~~]]] doUpdate ]]] (002422) ~~~~~]]] Splash_tmrALL_Timer>sys.frm.main_Load ]]] (002422) ~~~[[[ Main_Load [[[ (002422) ~~~~~[[[ Customers_Load [[[ (002422) ~~~~~~~~~~~~~~~Ok marker (002422) ~~~~~~~~[[[ Customers_setList [[[ (002422) ~~~~~~~~~~~~~~~]]] Customers_setList ]]] (002422) ~~~~~~~~[[[ doUpdate [[[ (002422) ~~~~~~~~~~~~~~~]]] doUpdate ]]] (002422) ~~~~~~~~[[[ Customers_FillList [[[ (002422) ~~~~~~~~~~~~~~~]]] Customers_FillList ]]] (002422) ~~~~~~~~[[[ Customers_cBar_Resize [[[ (002422) ~~~~~~~~~~~~~~~]]] Customers_cBar_Resize ]]] (002422) ~~~~~~~~[[[ Customers_cBar_Resize [[[ (002422) ~~~~~~~~~~~~~~~]]] Customers_cBar_Resize ]]] (002422) ~~~~~~~~~~]]] Customers_Load ]]] (002422) ~~~~~[[[ Parts_Load [[[ (002423) ~~~~~~~~[[[ Parts_cBar_HeightChanged [[[ (002423) ~~~~~~~~~~~~~~~]]] Parts_cBar_HeightChanged ]]] (002423) ~~~~~~~~[[[ Parts_cBar_HeightChanged [[[ (002423) ~~~~~~~~~~~~~~~]]] Parts_cBar_HeightChanged ]]] (002423) ~~~~~~~~[[[ Parts_SetList [[[ (002423) ~~~~~~~~~~~~~~~]]] Parts_SetList ]]] (002423) ~~~~~~~~[[[ Parts_FillList [[[ (002423) ~~~~~~~~~~~~~~~~~~~~Wrote to tag(1)::14 (002423) ~~~~~~~~~~~~~~~~~~~~Wrote to tag(2)::15 (002423) ~~~~~~~~~~~~~~~~~~~~Wrote to tag(3)::16 (002423) ~~~~~~~~~~~~~~~~~~~~Wrote to tag(4)::17 (002423) ~~~~~~~~~~~~~~~]]] Parts_FillList ]]] (002423) ~~~~~~~~~~]]] Parts_Load ]]] (002423) ~~~~~[[[ Invoice_Load [[[ (002423) ~~~~~~~~[[[ Inv_SetLV [[[ (002423) ~~~~~~~~~~~~~~~]]] Inv_SetLV ]]] (002423) ~~~~~~~~[[[ Inv_SwitchLV [[[ (002423) ~~~~~~~~~~~~~~~]]] Inv_SwitchLV ]]] (002423) ~~~~~~~~~~]]] Invoice_Load ]]] (002423) ~~~~~[[[ PC_Load [[[ (002423) ~~~~~~~~[[[ PC_InitLV [[[ (002423) ~~~~~~~~~~~~~~~]]] PC_InitLV ]]] (002423) ~~~~~~~~[[[ PC_FillLVpc [[[ (002423) ~~~~~~~~~~~~~~~]]] PC_FillLVpc ]]] (002423) ~~~~~~~~~~]]] PC_Load ]]] (002423) ~~~~~]]] Main_Load ]]] (002424) ~~~[[[ Main_mnuQuit_Click [[[ (002424) ~~~~~]]] Main_mnuQuit_Click>shutDownSys ]]] (002424) ~~~[[[ shutDownSys [[[ (002424) ~~~~~]]] shutDownSys ]]] (002424) ]]] SIMS ]]] |
Heb de database debugoutput er even uitgehaald omdat het anderd te groot werd
Anoniem: 39126
Nog even ontopic: volhouden is ook erg belangrijk. Normaalgesproken kost debuggen veel meer tijd dan het coden zelf. Het is dan ook vaak efficient om je code zeer netjes en goeddoordacht te schrijven omdat er dan meestal veel minder bugs ingebracht worden. Als een programma een zooitje is, dan is herschrijven bijna altijd sneller dan debuggen...
Nergens heb ik zó'n hekel aan als een foutmelding/crash met de melding 'Could not perform the requested action' of iets in die geest.
Als de foutmelding al aangeeft WAT er foutging en WAAROM het foutging ('TBackupService.BackupDatabase : Could not make a backup because the requested database is not available', 'TBar.CallFoo: Could not call method XXX on class TFoo because the object was nil') scheelt al zoveel zoekwerk, dat het zeker de moeite loont om in een foutmelding op te nemen: de classname, de methodname en de oorzaak van de fout. Let wel, de gebruiker krijgt dit natuurlijk niet voor z'n kiezen, de programmeur kan het bv uit de logfiles vissen.
Voor bugs die geen error produceren, als het gewenste gedrag dus schijnbaar uitgevoerd wordt, gebruik ik meestal de backtracking strategie. Ik zet een breakpoint op het punt waar het gedrag aantoonbaar niet is wat ik wilde, wacht tot de code daar komt en ga dan de callstack af om te kijken waar er iets vreemds aan de hand is.
Na het inschakelen van een "meer ervaren iemand" bleek dat er inderdaad ergens wat fout was gegaan met het toewijzen van geheugen aan een variable. Dit bleek op een pentium 3 WEL goed te gaan, en op een ander systeem niet, daar bleek het het geheugen waar de variable in stond te overschrijven waardoor het programma crashte... Erg irritand, en door die persoon zijn hulp waren we er ongetwijfeld nooit achter gekomen....
T: @mark_prins - Kick ass developers: www.omniscale.nl - HT: Where it all went wrong...
Maar de meeste reacties hier tonen dat er uiteindelijk misschien toch niet echt een andere manier is dat stappen, breaks, isoleren en vooral doorzetten.
Maar zien jullie debuggen nou als een techniek apart, dus iets wat met ervaring komt. Of meer als iets van goed inzicht in je programma/de taal
"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs
Op zondag 16 juni 2002 00:59 schreef _Mo_ het volgende:
Zo zie je maar weer: Intel rules* .oisyn runs from all AMD fans

wil je weten wat er gebeurt als ik op dit knopje druk?
(of die ernaast, kun je ook leuke dingen mee uithalen
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Anoniem: 3057
1) Bepaal duidelijk wat het probleem is, dus
a) wat er fout gaat (foutmelding)
b) wanneer het fout gaat (omstandigheden, handelingen, etc)
c) probeer de fout te reproduceren
2) Probeer te begrijpen en/of onderzoeken (zoeken in manuals met foutmeldingstekst bijv.), op basis van de info van punt 1 wat de bug zou kunnen zijn. Als dit triviaal is, fix het en test of het werkt. Zo niet, ga door.
3) Probeer te lokaliseren in welk grootst te onderscheiden stuk code het probleem zich voordoet, en zoek vanaf daar verder naar totdat je de kleinst mogelijke eenheid code hebt gevonden waarin de fout zich voordoet.
4) Loop stap voor stap door de code in dit kleinst mogelijke stuk code heen, waarbij je vooral let op:
a) waarden van relevante variabelen
b) calls naar externe functies/objecten/etc., die evt. onvoorspebaar of incorrect gedrag vertonen
c) niet afgevangen condities (Null waarden, geen records gereturned, negatieve waarden, verkeerd type waarden, etc.)
d) syntax vergissingen (bijv. "=" gebruiken als vergelijkingsoperator waar je "==" zou moeten gebruiken)
e) correctheid van (loop) condities ('out of bounds' problemen, '>' dat '>=' zou moeten zijn, etc.)
Speciale gevallen
SQL Queries
Als je dynamisch een SQL querie opbouwt, en die geeft problemen (onverwachte resultaten, syntax errors), print dat de query uit.
Als je dan niet in 1 slag op je oog* ziet wat het probleem is, open dan een directe connectie naar de database en voer de query handmatig uit, en speel ermee tot die wel goed is voordat je de code aanpast.
Connecties tussen verschillende systemen
Als je van deel A naar deel B een connectie maakt (COM call, message queue, HTTP call, CORBA call, etc), zorg dan dat je direct voor de uitgang van systeem A en na de ingang bij systeem B alle waarden logt, zodat je precies kan vergelijken of deze overeenkomen, en je zeker weet in welk deel het probleem zit.
Als je het probleem nu nog niet ziet of kunt oplossen, isoleer dat precies de regel code die de fout triggert, en haal er een buitenstaander bij, die een frisse blik op jouw code kan werpen.
HTH
* ) Voor mensen die de eeuwenoude traditie in Nederlandse humor van woord-/taalgrapjes niet kent, bij deze een uitleg: in 1 slag op je oog is een taalverbastering van in 1 oogopslag, puur bedoeld als komische noot in dit verder vrij droge stukje tekst, iets wat het effect zou moeten versterken.
* Anoniem: 3057 zucht en schudt het hoofd
[off-topic]Op zondag 16 juni 2002 05:50 schreef MrX het volgende:
... 1 slag op je oog ...
Jij mag je nederlands wel eens gaan debuggen, zie bovenstaand stappenplan
[/off-topic]
- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!
Anoniem: 47174
- Zoveel mogelijk code zelf schrijven (omslachtig, maar je weet altijd precies wat er gebeurt, en het is leuker)
- Gemoduleerd werken, net zolang aan een module werken tot je die 'bugvrij' verklaard hebt. Zodat, als je de module gebruikt, er van uit kunt gaan dat daar de bug niet in zit.
- Jezelf aan leren variabelen te initializeren, geheugen altijd vrij te geven, consequente naamgeving gebruiken, en netuurlijk veeeeeeel oefenen....
- Ik gebruik (in C/C++) altijd een eigen gemaakt alloc loggertje, waardoor ik automatisch alle memory-leaks detecteer. Wanneer ik geen memory-leaks heb aan het eind van mijn programma, weet ik dat ik op een juiste manier met de pointer e.d ben omgegaan.
Verder moet ik zeggen dat ik het debuggen steeds makkelijker ga vinden, gewoon steeds een stapje verder en met steppen/tracen zie je altijd wel waar de prob zit.
edit: opmaak
http://gathering.tweakers.net/forum/list_messages/392390/#debuggenOp zondag 16 juni 2002 05:50 schreef MrX een faqbaar stukje
Doet iets met Cloud (MS/IBM)
Zeker als je met gd een grafisch bestand wil maken en na een tijd blijkt de code plots niet meer te werken...
(semi-ot: voor de échte bughunters: http://www.phrea.com/stuff/noppes/
Copyright Auteur heeft Tweakers.net BV geen exclusieve licentie op bovenstaande post verleend. Voorafgaande en uitdrukkelijke schriftelijke toestemming van Tweakers.net BV is dus niet noodzakelijk voor het vermenigvuldigen van bovenstaande post
Lost ze de bugs ook op?Op zondag 16 juni 2002 15:11 schreef Bart Coppens het volgende:
(semi-ot: voor de échte bughunters: http://www.phrea.com/stuff/noppes/)
"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs
Anoniem: 47953
Misschien heb je dan wat aan ActiveSate Komodo: http://www.activestate.com/Products/Komodo/Op zondag 16 juni 2002 15:11 schreef Bart Coppens het volgende:
Voor PHP ben ik nog niet echt een goede debugenviroment tegengekomen
Ben ik het niet mee eens. Als jij een fantastisch programma schrijft, maar een klein lullig foutje maakt met een pointer kan je daar enorm lang naar op zoek zijn (mijn laatste paar dagen dus hehe). Maar daardoor hoeft het programma nog niet slecht te zijn.Op zondag 16 juni 2002 16:39 schreef Skizmo het volgende:
niet lullig bedoeld maar. . . goeie software is makkelijk te debuggen . . .oftewel .. . als je laaaaaaaaaaaaaang aan het debuggen bent .. kun je beter overnieuw beginnen . .want dan is je code waarschijnlijk ook niet zo denderend
Op m'n stage ben ik 4 weken op zoek geweest naar een bug in m'n eigen code, maar na ik weg was daar hebben ze nog een week of twee doorgezocht en bleek het probleem bij hun eigen string class te zijn. Kortom, was ik opnieuw begonnen, had ik precies hetzelfde gehad.
"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs
De ervaring leert echter dat in een goed opgebouwd programma, foutieve code (relatief) makkelijk te isoleren is. Debugging tools die checken of je niet over grenswaarden van pointers heenschrijft en alle gealloceerde ruimte wel opruimt enzo, helpen natuurlijk ontzettend, maar als je die niet hebt, ben je echt afhankelijk van de structuur van je programma.Op zondag 16 juni 2002 16:44 schreef _Mo_ het volgende:
Ben ik het niet mee eens. Als jij een fantastisch programma schrijft, maar een klein lullig foutje maakt met een pointer kan je daar enorm lang naar op zoek zijn (mijn laatste paar dagen dus hehe). Maar daardoor hoeft het programma nog niet slecht te zijn.
In een 'goed' programma (naar mijn mening) zijn alle functies zo veel als redelijkerwijs mogelijk is vrij van neveneffecten. Voor objecten geldt dat de interne staat altijd consistent is.
Het gaat misschien wat ver om bij elk opject, elke methode, elke functie en elk algoritme de pre/post-condities en invarianten te documenteren, maar zelfs als ze niet expliciet genoemd zijn kunnen ze impliciet aanwezig zijn.
Ik ben het dus niet helemaal met Skizmo eens, maar ik denk dat zijn stelling gemiddelde genomen vaker wel dan niet opgaat.
en daar vind ik het debuggen redelijk moeilijk...
ik doet het meestal stap voor stap, kijken waar er iets fout gaat, en veel variabelen echo-en die normaal niet ge-echo-ed worden, om te kijen of ze wel de waarde hebben die ze horen te hebben
De grootste Nederlandstalige database met informatie over computers met zoekfunctie!!
WIL IK OOK!!Op zondag 16 juni 2002 01:08 schreef .oisyn het volgende:
[..]
[afbeelding]
wil je weten wat er gebeurt als ik op dit knopje druk?
(of die ernaast, kun je ook leuke dingen mee uithalen)
De grootste Nederlandstalige database met informatie over computers met zoekfunctie!!
Als de goede debug tools (zoals Step, trace etc.) beschikbaar zijn benut ik die uiteraard.
Nu werk ik echter in een omgeving waar die niet beschikbaar zijn dus debug ik idd door naar de STDOUT te schrijven.
Wat overigens ook helpt bij het debuggen is proberen zoveel mogelijk Errors, exceptions of hoe je ze ook noemt af te vangen en te loggen in een file.
It’s nice to be important but it’s more important to be nice
[..]
En het leuke is, door het gebruik van een debugger kan het ook nog eens zo zijn dat de bug dus niet optreedt, dus zul je m ook niet vinden
[..]
En dat is werkelijk het meest irritante verschijnsel dat er bestaat. Wel eens meegemaakt op een S/390. Uiteindelijk bleek dat er een index out of bounds ging, maar als je met de debugger aan draaide has íe net genoeg geheugen extra om niet op z'n plaat te gaan.
OVerigens zorg ik er tegenwoordig vanaf het de start van het coderen voor dat ik, ook zonder debugger, een redelijk idee heb van wat er gebeurt in de code. Omdat dat de laatste tijd allemaal in Java gaat is Log4J de logische keus. Gewoon op strategische plekken aangeven wat je programma doet en je hbet later veel minder werk om uit te zoeken op welke plek het fout gaat.
With the light in our eyes, it's hard to see.