Thread View: pl.comp.lang.delphi
13 messages
13 total messages
Started by apl
Fri, 26 Jun 2020 05:03
callChain
Author: apl
Date: Fri, 26 Jun 2020 05:03
Date: Fri, 26 Jun 2020 05:03
71 lines
2973 bytes
2973 bytes
Drodzy koledzy, każdy z was wie, jakim koszmarem jest debugowanie programu, zwłaszcza takiego, do którego sięgamy po wielu latach celem przebudowy nie mówiąc już o cudzych kodach źródłowych. Bardzo pomocna w tym przypadku jest znajomość całego łańcucha wołań prowadzących do danego podprogramu. W tym poście chciałbym podzielić się bardzo prostym wynalazkiem i poddać go waszej krytycznej ocenie. Przypuśćmy, że śledzonym podprogramem jest procedure sub2. Mój "chwyt" polega na dodaniu parametru formalnego callChain:string przekazywanego przez wartość oraz na zamieszczeniu na początku treści wykonawczej instrukcji callChain:=callChain+'>sub2'; Zabieg ten należy powtórzyć w każdym podprogramie wołającym wybrany śledzony (tu: sub2) z tym, że zamiast sub2 wpisujemy nazwę podprogramu wołającego z dodatkiem znaku '>' rozdzielającego nazwy w tworzonym łańcuchu. Krytyczne fragmenty treści sub2 obejmujemy instrukcją try except end, gdzie zamieszczamy showMessage informujący o błędzie. W przypadku iteracji, czy rekurencji przydatne będzie proliferowanie wartości zmiennych sterujących - dodajemy wtedy wymagane parametry formalne przekazywane przez wartość. Poniżej zamieszczam maksymalnie uproszczony przykład ilustrujący tę ideę zawierający iterację i rekurencję, stąd parametry i,n:word. Tak wzbogacony program daje nieoceniony wgląd w bieżący stan wykonania programu odczytując aktualną wartość callChain. Program niejako buduje się sam, żądając brakujących parametrów formalnych podczas kompilacji. Tym postem chciałbym zapoczątkować wakacyjną akcję dzielenia się na tym forum swoimi chwytami warsztatowymi. Gorąco zachęcam!!! Pozdrawiam, apl P.S. Błagam, powiedzcie PADowi NIE!!! procedure sub2(callChain:string;i,n:word); var r:real; begin callChain:=callChain+'>sub2'; r:=0; try //enclosure of a critical fragment r:=r/r; except showMessage('Error occured in a call chain "'+callChain+'". Iteration step='+intToStr(i)+'. Recursion step='+intToStr(n)) end; end;{sub2} procedure sub1(callChain:string;i,n:word); begin callChain:=callChain+'>sub1'; sub2(callChain,i,n); end;{sub1} procedure sub0(callChain:string;n:word); var i:shortInt; begin callChain:=callChain+'>sub0'; for i:=0 to 5 do sub1(callChain,i,n); if n<3 then sub0(callChain,n+1); //recursion end;{sub0} end. Wołanie z poziomu formatki, to np.: procedure TForm1.Button1Click(Sender: TObject); begin sub0('>TForm1.Button1Click',0); end;
Re: callChain
Author: apl
Date: Fri, 26 Jun 2020 06:20
Date: Fri, 26 Jun 2020 06:20
10 lines
598 bytes
598 bytes
Wyobraź sobie kolego, że postać exe liczy ci cóś przez 10 godzin i pada. Gdzie twój call stack??? Albo pada u klienta - gdzie twój call stack? Tu możesz dowolnie opisać potencjalnie zaistniałą sytuację i dostać perfekcyjny komunikat. Poza tym call stack, jak się można łatwo przekonać daje, delikatnie mówiąc, zagmatwany obraz (D2005). Po co się z tym męczyć, skoro tak łatwo można wprowadzić własne, adekwatne śledzenie i komunikaty? Pozdrawiam, apl
Re: callChain
Author: apl
Date: Fri, 26 Jun 2020 06:22
Date: Fri, 26 Jun 2020 06:22
8 lines
366 bytes
366 bytes
W dniu piątek, 26 czerwca 2020 14:11:41 UTC+2 użytkownik Jan Drawski napisał: > > P.S. Błagam, powiedzcie PADowi NIE!!! > > Miałem na niego nie głosować ale że tu wrzucasz politykę to zagłosuję na > niego. Ten twój wpis o tym ostatecznie zadecydował. Życzę powodzenia, pozdrawiam.
Re: callChain
Author: apl
Date: Fri, 26 Jun 2020 12:18
Date: Fri, 26 Jun 2020 12:18
98 lines
2639 bytes
2639 bytes
> > Program, który wkleiłeś nie zadziała jak opisałeś, sprawdź. > > -- > pozdrawiam > Roman Tyczka Dziekuję za zainteresowanie moim pomysłem. Być może Twoje oczekiwania są inne, a być może patrzę i czegoś nie widzę (tę wersję upraszczałem korzystając z Notatnika) Na wszelki wypadek wklejam jednak wersję skopiowaną wprost z edytora Delphi. Jest ona minimalnie bogatsza, a mianowicie w proc. sub0 jest instrukcja if n=0 then callChain:=callChain+'>sub0'; zamiast poprzedniej callChain:=callChain+'>sub0'; Warunek if n=0 zapobiega powtarzaniu się nazwy '>sub0' w wołaniach rekurencyjnych aby skrócić łańcuch odnotowujący te wołania w sytuacji, gdy mamy licznik takich wołań. Zamieszczam tu pełne treści obu modułów składających się na program testowy. W efekcie np. wykonania 1. kroku otrzymasz komunikat: Error occured in call chain ">TForm1.Button1Click>sub0>sub1>sub2". Iteration step=0. Recursion step=0 czyli informację, że błąd powstał w procedurze sub2 wołanej z procedury sub1, która była wołana z procedury sub0, a ta z kolei ze zdarzenia OnClick przycisku button1. Pozdrawiam, apl unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses unit2; procedure TForm1.Button1Click(Sender: TObject); begin sub0('>TForm1.Button1Click',0); end; end. unit Unit2; interface procedure sub0(callChain:string;n:word); implementation uses dialogs,SysUtils; procedure sub2(callChain:string;i,n:word); var r:real; begin callChain:=callChain+'>sub2'; r:=0; try //enclosure of a critical fragment r:=r/r; except showMessage('Error occured in call chain "'+callChain+'". Iteration step='+intToStr(i)+'. Recursion step='+intToStr(n)) end; end;{sub2} procedure sub1(callChain:string;i,n:word); begin callChain:=callChain+'>sub1'; sub2(callChain,i,n); end;{sub1} procedure sub0(callChain:string;n:word); var i:shortInt; begin if n=0 then callChain:=callChain+'>sub0'; for i:=0 to 5 do sub1(callChain,i,n); if n<3 then sub0(callChain,n+1); //recursion end;{sub0} end.
Re: callChain
Author: apl
Date: Fri, 26 Jun 2020 12:20
Date: Fri, 26 Jun 2020 12:20
74 lines
3172 bytes
3172 bytes
W dniu piątek, 26 czerwca 2020 14:03:13 UTC+2 użytkownik apl napisał: > Drodzy koledzy, > każdy z was wie, jakim koszmarem jest debugowanie programu, zwłaszcza takiego, do którego sięgamy po wielu latach celem przebudowy nie mówiąc już o cudzych kodach źródłowych. > Bardzo pomocna w tym przypadku jest znajomość całego łańcucha wołań prowadzących do danego podprogramu. > W tym poście chciałbym podzielić się bardzo prostym wynalazkiem i poddać go waszej krytycznej ocenie. > Przypuśćmy, że śledzonym podprogramem jest procedure sub2. > Mój "chwyt" polega na dodaniu parametru formalnego callChain:string przekazywanego przez wartość oraz na zamieszczeniu na początku treści wykonawczej instrukcji callChain:=callChain+'>sub2'; Zabieg ten należy powtórzyć w każdym podprogramie wołającym wybrany śledzony (tu: sub2) z tym, że zamiast sub2 wpisujemy nazwę podprogramu wołającego z dodatkiem znaku '>' rozdzielającego nazwy w tworzonym łańcuchu. Krytyczne fragmenty treści sub2 obejmujemy instrukcją try except end, gdzie zamieszczamy showMessage informujący o błędzie. W przypadku iteracji, czy rekurencji przydatne będzie proliferowanie wartości zmiennych sterujących - dodajemy wtedy wymagane parametry formalne przekazywane przez wartość. Poniżej zamieszczam maksymalnie uproszczony przykład ilustrujący tę ideę zawierający iterację i rekurencję, stąd parametry i,n:word. > Tak wzbogacony program daje nieoceniony wgląd w bieżący stan wykonania programu odczytując aktualną wartość callChain. Program niejako buduje się sam, żądając brakujących parametrów formalnych podczas kompilacji. > Tym postem chciałbym zapoczątkować wakacyjną akcję dzielenia się na tym forum swoimi chwytami warsztatowymi. Gorąco zachęcam!!! > Pozdrawiam, apl > > P.S. Błagam, powiedzcie PADowi NIE!!! > > > procedure sub2(callChain:string;i,n:word); > var r:real; > begin > callChain:=callChain+'>sub2'; > r:=0; > try //enclosure of a critical fragment > r:=r/r; > except > showMessage('Error occured in a call chain "'+callChain+'". Iteration step='+intToStr(i)+'. Recursion step='+intToStr(n)) > end; > end;{sub2} > > procedure sub1(callChain:string;i,n:word); > begin > callChain:=callChain+'>sub1'; > sub2(callChain,i,n); > end;{sub1} > > procedure sub0(callChain:string;n:word); > var i:shortInt; > begin > callChain:=callChain+'>sub0'; > for i:=0 to 5 do sub1(callChain,i,n); > if n<3 then sub0(callChain,n+1); //recursion > end;{sub0} > end. > > Wołanie z poziomu formatki, to np.: > > > procedure TForm1.Button1Click(Sender: TObject); > begin > sub0('>TForm1.Button1Click',0); > end;
Re: callChain
Author: Jan Drawski
Date: Fri, 26 Jun 2020 14:11
Date: Fri, 26 Jun 2020 14:11
3 lines
166 bytes
166 bytes
> P.S. B³agam, powiedzcie PADowi NIE!!! Mia³em na niego nie g³osowaæ ale ¿e tu wrzucasz politykê to zag³osujê na niego. Ten twój wpis o tym ostatecznie zadecydowa³.
Re: callChain
Author: Tomek D
Date: Fri, 26 Jun 2020 14:18
Date: Fri, 26 Jun 2020 14:18
17 lines
1989 bytes
1989 bytes
W dniu 26.06.2020 o 14:03, apl pisze: > > Drodzy koledzy, > każdy z was wie, jakim koszmarem jest debugowanie programu, zwÅaszcza takiego, do którego siÄgamy po wielu latach celem przebudowy nie mówiÄ c już o cudzych kodach źródÅowych. > Bardzo pomocna w tym przypadku jest znajomoÅÄ caÅego ÅaÅcucha woÅaÅ prowadzÄ cych do danego podprogramu. > W tym poÅcie chciaÅbym podzieliÄ siÄ bardzo prostym wynalazkiem i poddaÄ go waszej krytycznej ocenie. > PrzypuÅÄmy, że Åledzonym podprogramem jest procedure sub2. > Mój "chwyt" polega na dodaniu parametru formalnego callChain:string przekazywanego przez wartoÅÄ oraz na zamieszczeniu na poczÄ tku treÅci wykonawczej instrukcji callChain:ÊllChain+'>sub2'; Zabieg ten należy powtórzyÄ w każdym podprogramie woÅajÄ cym wybrany Åledzony (tu: sub2) z tym, że zamiast sub2 wpisujemy nazwÄ podprogramu woÅajÄ cego z dodatkiem znaku '>' rozdzielajÄ cego nazwy w tworzonym ÅaÅcuchu. Krytyczne fragmenty treÅci sub2 obejmujemy instrukcjÄ try except end, gdzie zamieszczamy showMessage informujÄ cy o bÅÄdzie. W przypadku iteracji, czy rekurencji przydatne bÄdzie proliferowanie wartoÅci zmiennych sterujÄ cych - dodajemy wtedy wymagane parametry formalne przekazywane przez wartoÅÄ. Poniżej zamieszczam maksymalnie uproszczony przykÅad ilustrujÄ cy tÄ ideÄ zawierajÄ cy iteracjÄ i rekurencjÄ, stÄ d parametry i,n:word. > Tak wzbogacony program daje nieoceniony wglÄ d w bieÅ¼Ä cy stan wykonania programu odczytujÄ c aktualnÄ wartoÅÄ callChain. Program niejako buduje siÄ sam, Å¼Ä dajÄ c brakujÄ cych parametrów formalnych podczas kompilacji. Może nie rozumiem problemu autora wÄ tku, ale w Årodowisku Delphi podczas debugowania jest dostÄpne okno "Call stack", które pokazuje ÅcieżkÄ wywoÅaÅ. I nie wymaga modyfikacji kodu źródÅowego. Ponadto mamy zewnÄtrzne narzÄdzia takie jak madExcept, EurekaLog, CodeSite, które wydatnie uÅatwiajÄ lokalizacjÄ bÅÄdów. Tomek D.
Re: callChain
Author: Tomek D
Date: Fri, 26 Jun 2020 15:49
Date: Fri, 26 Jun 2020 15:49
11 lines
679 bytes
679 bytes
W dniu 26.06.2020 o 15:20, apl pisze: > Wyobraź sobie kolego, że postać exe liczy ci cóś przez 10 godzin i pada. Gdzie twój call stack??? > Albo pada u klienta - gdzie twój call stack? Tu możesz dowolnie opisać potencjalnie zaistniałą sytuację i dostać perfekcyjny komunikat. > Poza tym call stack, jak się można łatwo przekonać daje, delikatnie mówiąc, zagmatwany obraz (D2005). Po co się z tym męczyć, skoro tak łatwo można wprowadzić własne, adekwatne śledzenie i komunikaty? > > Pozdrawiam, apl > Proszę zapoznaj się z madExcept, EurekaLog - one dają Ci Call Stack dla działającej aplikacji i wiele więcej. Po co się męczyć. Tomek D.
Re: callChain
Author: Roman Tyczka
Date: Fri, 26 Jun 2020 17:27
Date: Fri, 26 Jun 2020 17:27
54 lines
2797 bytes
2797 bytes
On Fri, 26 Jun 2020 05:03:12 -0700 (PDT), apl wrote: > Drodzy koledzy, > każdy z was wie, jakim koszmarem jest debugowanie programu, zwÅaszcza takiego, do którego siÄgamy po wielu latach celem przebudowy nie mówiÄ c już o cudzych kodach źródÅowych. > Bardzo pomocna w tym przypadku jest znajomoÅÄ caÅego ÅaÅcucha woÅaÅ prowadzÄ cych do danego podprogramu. > W tym poÅcie chciaÅbym podzieliÄ siÄ bardzo prostym wynalazkiem i poddaÄ go waszej krytycznej ocenie. > PrzypuÅÄmy, że Åledzonym podprogramem jest procedure sub2. > Mój "chwyt" polega na dodaniu parametru formalnego callChain:string przekazywanego przez wartoÅÄ oraz na zamieszczeniu na poczÄ tku treÅci wykonawczej instrukcji callChain:ÊllChain+'>sub2'; Zabieg ten należy powtórzyÄ w każdym podprogramie woÅajÄ cym wybrany Åledzony (tu: sub2) z tym, że zamiast sub2 wpisujemy nazwÄ podprogramu woÅajÄ cego z dodatkiem znaku '>' rozdzielajÄ cego nazwy w tworzonym ÅaÅcuchu. Krytyczne fragmenty treÅci sub2 obejmujemy instrukcjÄ try except end, gdzie zamieszczamy showMessage informujÄ cy o bÅÄdzie. W przypadku iteracji, czy rekurencji przydatne bÄdzie proliferowanie wartoÅci zmiennych sterujÄ cych - dodajemy wtedy wymagane parametry formalne przekazywane przez wartoÅÄ. Poniżej zamieszczam maksymalnie uproszczony przykÅad ilustrujÄ cy tÄ ideÄ zawierajÄ cy iteracjÄ i rekurencjÄ, stÄ d parametry i,n:word. > Tak wzbogacony program daje nieoceniony wglÄ d w bieÅ¼Ä cy stan wykonania programu odczytujÄ c aktualnÄ wartoÅÄ callChain. Program niejako buduje siÄ sam, Å¼Ä dajÄ c brakujÄ cych parametrów formalnych podczas kompilacji. > Tym postem chciaÅbym zapoczÄ tkowaÄ wakacyjnÄ akcjÄ dzielenia siÄ na tym forum swoimi chwytami warsztatowymi. GorÄ co zachÄcam!!! > Pozdrawiam, apl > > P.S. BÅagam, powiedzcie PADowi NIE!!! > > > procedure sub2(callChain:string;i,n:word); > var r:real; > begin > callChain:ÊllChain+'>sub2'; > r:=0; > try //enclosure of a critical fragment > r:=r/r; > except > showMessage('Error occured in a call chain "'+callChain+'". Iteration step='+intToStr(i)+'. Recursion step='+intToStr(n)) > end; > end;{sub2} > > procedure sub1(callChain:string;i,n:word); > begin > callChain:ÊllChain+'>sub1'; > sub2(callChain,i,n); > end;{sub1} > > procedure sub0(callChain:string;n:word); > var i:shortInt; > begin > callChain:ÊllChain+'>sub0'; > for i:=0 to 5 do sub1(callChain,i,n); > if n<3 then sub0(callChain,n+1); //recursion > end;{sub0} > end. > > WoÅanie z poziomu formatki, to np.: > > > procedure TForm1.Button1Click(Sender: TObject); > begin > sub0('>TForm1.Button1Click',0); > end; Program, który wkleiÅeÅ nie zadziaÅa jak opisaÅeÅ, sprawdź. -- pozdrawiam Roman Tyczka
Re: callChain
Author: zpksoft
Date: Sat, 27 Jun 2020 00:33
Date: Sat, 27 Jun 2020 00:33
13 lines
578 bytes
578 bytes
W dniu piątek, 26 czerwca 2020 21:18:31 UTC+2 użytkownik apl napisał: >... > czyli informację, że błąd powstał w procedurze sub2 wołanej z procedury sub1, która była wołana z procedury sub0, a ta z kolei ze zdarzenia OnClick przycisku button1. >... Błąd (logiczny) mógł powstać dużo wcześniej tylko (maszynowy) objawił się dopiero tutaj. Nie wskazuje Ci to więc miejsca wystąpienia błędu tylko miejsce wykrzaczenia programu. Paweł
Re: callChain
Author: apl
Date: Sat, 27 Jun 2020 02:29
Date: Sat, 27 Jun 2020 02:29
19 lines
978 bytes
978 bytes
> > Błąd (logiczny) mógł powstać dużo wcześniej tylko (maszynowy) objawił się dopiero tutaj. Nie wskazuje Ci to więc miejsca wystąpienia błędu tylko miejsce wykrzaczenia programu. > > Paweł Tak, to powszechnie znana prawda, ale od czegoś konkretnego trzeba zacząć. Pewnym mankamentem metody jest to, że trzeba wpisywać nazwę podprogramu zamiast odwoływać się do pewnej zmiennej, której wartość taką nazwę zawiera (W VB np., zmienne są jakoś tam numerowane, ale nie zgłębiałem tego tematu). Niestety, popularna dokumentacja nie zawiera takiej informacji, ale być może ktoś z kolegów posiada taką informację i podzieli się nią na forum. Wiedza taka może znaleźć rozliczne zastosowania w konstrukcji programów. Pozdrawiam, apl
Re: callChain
Author: zpksoft
Date: Sat, 27 Jun 2020 02:45
Date: Sat, 27 Jun 2020 02:45
26 lines
1280 bytes
1280 bytes
W dniu sobota, 27 czerwca 2020 11:29:52 UTC+2 użytkownik apl napisał: > > > > Błąd (logiczny) mógł powstać dużo wcześniej tylko (maszynowy) objawił się dopiero tutaj. Nie wskazuje Ci to więc miejsca wystąpienia błędu tylko miejsce wykrzaczenia programu. > > > > Paweł > > Tak, to powszechnie znana prawda, ale od czegoś konkretnego trzeba zacząć. Pewnym mankamentem metody jest to, że trzeba wpisywać nazwę podprogramu zamiast odwoływać się do pewnej zmiennej, której wartość taką nazwę zawiera (W VB np., zmienne są jakoś tam numerowane, ale nie zgłębiałem tego tematu). Niestety, popularna dokumentacja nie zawiera takiej informacji, ale być może ktoś z kolegów posiada taką informację i podzieli się nią na forum. Wiedza taka może znaleźć rozliczne zastosowania w konstrukcji programów. > Pozdrawiam, > apl Jak dla mnie to mankamentem jest ingerencja w kod, szpikowanie procedur tymi informacjami. Ale jak kto lubi :) Ja wolę postawić breakpoint i przeanalizować wartości zmiennych.
Re: callChain
Author: apl
Date: Sun, 28 Jun 2020 02:24
Date: Sun, 28 Jun 2020 02:24
11 lines
279 bytes
279 bytes
Dzięki kolego za ten tip, zapoznam się z tymi programami apl > > Proszę zapoznaj się z madExcept, EurekaLog - one dają Ci Call Stack dla > działającej aplikacji i wiele więcej. Po co się męczyć. > > Tomek D.
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads