1.11 — आपके program
को Debug करना (stepping
और breakpoints)
Syntax और semantic errors
Programming काफी मुश्किल हो सकता है, और आप programs
लिखने
समय कई तरह की गलतियाँ कर सकते हो । Errors मुख्यतः दो तरह के होते हैं: syntax
errors, और semantic
errors (logic errors) ।
Syntax error program में तब आते हैं, जब आपका लिखा हुआ कोई statement
C++ के grammar
के
अनुसार सही ना हो । आप statement के अंत में semicolon
लगाना
भूल जाते हो, बिना declare किये किसी variable को use करने की कोशिश करते हो,
braces या paranthesis
के
जोड़े में केवल एक को लिखते हो या फिर किसी string को terminate
करना
भूल जाते हो, ऐसे errors syntax errors की category में आते हैं । उदाहरण के लिए, नीचे दिए गए program
में
कुछ syntax errors हैं :
|
1
2
3
4
5
|
#include <iostream>; // preprocessor statements के अंत में semicolon लगाना
गलत है
int main()
{
std:cout < "Hi there; << x; // operators (: और <) invalid हैं, string terminated नहीं है (" symbol अंत में छुट गया है), और variable x undefined है
return 0 // statement के
अंत में semicolon नहीं लगा है
|
अच्छी बात ये है, की compiler
साधारणतः
हर syntax error को catch कर warning
या error दे देता है, इसलिए आप इन्हें आसानी से fix कर सकते हो । इसलिए, ये program
में जब
तक सारे errors न मिल जाएँ, तब तक इसे compile
करने
जितना ही आसान है ।
यदि आपका program अच्छी तरह से compile
हो रहा
है, तो भी program से expected
(वांछित)
result(s) प्राप्त करना थोड़ा मुश्किल साबित हो सकता है । यदि program
के syntatically
(C++ के grammar
के
अनुसार) सही होने के बाद भी ये आपका मनचाहा result नहीं दे रहा है, तो ऐसे errors को sematic errorsकहते हैं ।
कभी-कभी semanatic errors के कारण आपका program crash भी हो सकता है, उदाहरण के लिए, जब आप किसी number को 0 से divide करोगे (अर्थात् भाग दोगे), तो आपका program संभवतः crash कर जायेगा :
कभी-कभी semanatic errors के कारण आपका program crash भी हो सकता है, उदाहरण के लिए, जब आप किसी number को 0 से divide करोगे (अर्थात् भाग दोगे), तो आपका program संभवतः crash कर जायेगा :
|
1
2
3
4
5
6
7
8
9
|
#include <iostream>
int main()
{
int a = 10;
int b = 0;
std::cout << a << " / " << b << " = " << a / b; // 0 से
भाग देने पर result
undefined है
return 0;
}
|
कभी-कभी, ये गलत values भी प्रदान कर सकते हैं:
|
1
2
3
4
5
6
7
|
#include <iostream>
int main()
{
std::cout << "Hello, word!"; // spelling error
return 0;
}
|
या
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
int add(int x, int y)
{
return x - y; // function के
नाम से लग रहा है ये values को add करेगा, पर
ऐसा नहीं है
}
int main()
{
std::cout << add(5, 3); // आप
सोचोगे program 8 print करेगा, लेकिन
console पर 2 print हुआ
मिलेगा
return 0;
}
|
दुर्भाग्यवश, compiler ऐसे errors को catch नहीं कर सकता, क्यूंकि compiler
को बस
इतना पता है की आपने code में क्या लिखा है, ये नहीं की आप code से क्या उम्मीद करते हो ।
ऊपर दिए गए उदाहरण में सारे errors का पता आसानी से लगाया जा
सकता है । लेकिन बड़े-बड़े programs में, कई semantic
errors केवल code को देखते रहने से पकड़ में
नहीं आते ।
Fortunately, यहाँ debugger काफी सुविधाजनक साबित हो सकता
है ।
Debugger
Debugger एक ऐसा computer
program है जो programmer
को ये control
करने
की अनुमति देता है, की program कैसे execute होगा और साथ ही ये भी दिखाता
है की program run करते हुए क्या-क्या output दे रहा है । उदाहरण के लिए,
programmer debugger का इस्तेमाल करते हुए किसी program
को line-by-line
execute करके
ये देख सकता है, की प्रत्येक पड़ाव में variables के क्या-क्या values
set हैं । Variable
के
वास्तविक value को programmer के सोचे गए value से compare
कर, या फिर code के execution
के path पर नज़र रखते हुए,
debugger किसी semantic
error को खोज
निकालने में हमारी काफी मदद कर सकता है ।
पहले के debuggers, जैसे की gdb, में command-line
interface होता
था, जहाँ programmer को कुछ commands type कर debugging
का काम
करना पड़ता था । इसके बाद के debuggers, (जैसे की Borland
का turbo debugger)
“graphical interface” के साथ आने लगे, ताकि उनके साथ काम करना और
ज्यादा आसान और मज़ेदार हो जाये । आजकल के लगभग सभी IDEs में एक integrated debugger मौजूद होता है -- ये editor में ही बना होता है या फिर
ऐसा कहा जाये की editor से ही जुड़ा होता है, ताकि आप एक ही environment
में codes को लिखने और debug करने का काम कर सके (इन दोनों
कामों के लिए, एक से दुसरे program में जाये बिना) ।
आज के लगभग हर debugger, basic features के बिलकुल एक जैसे standard
के साथ
आते हैं -- फिर भी, इनमें दिए गए menus कैसे arrange
किये
गए हैं और इनके लिए keyboard shortcuts क्या-क्या हैं, ये अलग-अलग IDEs में एक दुसरे से थोड़े अलग हो
सकते हैं । हमारे examples Microsoft Visual Studio 2005 Express के अनुसार लिखे गए हैं, फिर भी आपको अपने IDE में, यहाँ दिए गए features
को
ढूंढने के लिए काफी ज्यादा मेहनत करने की ज़रूरत नहीं पड़ेगी ।
आगे बढ़ने से पहले: ये पक्का कर ले की आपका program debug
build configuration का इस्तेमाल करने के लिए set है ।
Stepping
Stepping debugger का एक feature
है, जो आपको codes को line-by-line
(step through) execute करने की अनुमति देता है । इस तरह से आपको ये पता चलेगा, की आपका code किसी पड़ाव पर आपके सोचे गए
अनुसार काम कर रहा है या नहीं ।
Stepping commands 3 हैं : step into, step over, और step
out । हम
एक-एक कर के इनके बारे में जानेंगे ।
Step into
Step into command, code के अगले line को execute
करता
है । यदि इस line में किसी function को call किया गया है, तो step
into उस function
में
चला जायेगा और इसके बाद सारा control, function में सबसे ऊपर चला जायेगा ।
आइये एक आसान से program पर नज़र डालते हैं:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
void printValue(int nValue)
{
std::cout << nValue;
}
int main()
{
printValue(5);
return 0;
}
|
जैसा की आप जानते हो, जब कोई program
run होता
है, तो execution की शुरुआत main() function के call होने के साथ होती है ।
क्यूंकि हमे main के अन्दर से debug करना है, आइये हम “Step
into” command का प्रयोग करते हैं ।
Visual Studio 2005 Express में, debug
menu में
जाकर “Step into” का चुनाव कर ले, या फिर F11 key
press करें ।
यदि आप किसी दुसरे IDE का प्रयोग कर रहे हैं, तो इसके Menu में कहीं “Step Into” command खोजने की कोशिश कीजिये ।
यदि आप किसी दुसरे IDE का प्रयोग कर रहे हैं, तो इसके Menu में कहीं “Step Into” command खोजने की कोशिश कीजिये ।
जब आप ये करोगे, दो चीजें होनी चाहिए । पहला, क्यूंकि हमारा application
एक console
program है, तो सबसे पहले console
output window खुलना चाहिए । ये अभी बिलकुल खाली होगा क्यूंकि हमने अभी तक कुछ भी output नहीं किया है । दूसरा, आपको main
function की
बायीं ओर, opening brace ( { ) में एक marker दिखाई देना चाहिए । Visual
Studio 2005 Express में, ये marker एक पीला arrow होता है । यदि आप किसी दुसरे IDE का प्रयोग कर रहे हो, तो फिर इस जगह पर कुछ न कुछ
ज़रूर दिखना चाहिए ।

ये पीला marker ये बता रहा है की अगले execution
में pointed
line (वो line जिसपे marker है) ही execute
होगा ।
यहाँ पे, हमारा debugger हमे ये बता रहा है की अगला line जो execute
होने
वाला है, वो main() function के opening brace वाला line है । इसके बाद “Step
into” को फिर
से चुन लें ताकि opening brace वाला line execute हो जाये, और arrow अगले line में चला जाये ।

अब अगला line जो execute
होगा, वो printValue()
को call करने वाला line है । “Step
into” को फिर
से चुन लें । क्यूंकि printValue() एक function
call statement है, हमलोग इस function (printValue()) पर पहुँच जायेंगे , और arrow
printValue() में सबसे ऊपर दिखाई देने लगेगा ।

फिर से “Step into” को चुन ले ताकि printValue()
का opening
brace execute हो जाये ।
इसके बाद marker
std::cout << nValue; वाले line पर चला जायेगा ।
अब यहाँ "Step
over" को चुने (ये आपके code में केवल इसी line को execute
करेगा, न की operator
<< के code में पहुँच जायेगा) । क्यूंकि cout
statement अब execute
हो
चूका है, आप देखोगे की output window में 5 print
हो गया
है ।
इस function के closing brace को execute
करने
के लिए एक बार फिर से "Step into" को चुन लें । इसी के साथ,
printValue() का execution अब ख़त्म हो गया है और control
वापस main() पर चला गया गया है ।
आप देखोगे की arrow फिर से printValue()
को point कर रहा है!

यहाँ आप ये सोच सकते हो की debugger फिर से printValue()
को call करने वाला है, असल में debugger
ऐसा
इसलिए कर रहा है, ताकि आपको पता चल सके की ये इस function
से लौट
चूका है ।
इस बार "Step into" को दो बार select करें । अब हमने program
के हर
एक line को execute कर लिया है और इसलिए इस program
में
हमारा (debugging का) काम ख़त्म हो गया है । कुछ debuggers
program के
ख़त्म होने पर debugging के process को अपने आप बंद कर देंगे । पर
Visual Studio ऐसा नहीं करता और इसलिए यदि आप Visual
Studio इस्तेमाल
कर रहे हो, तो debugging session ख़त्म करने के लिए debug menu में से "Stop
Debugging" के option को चुन लो ।
ध्यान दे की "Stop Debugging" option का इस्तेमाल,
debugging के process
को
खत्म करने के लिए किसी भी जगह पर किया जा सकता है ।
Step over
"Step into" की तरह, Step over command
भी code के next
line को ही execute
करता
है । यदि इस line में कोई function call है, तो "Step
over" function के सारे codes को execute
कर के control
आप पे
छोड़ देता है ।
ध्यान दे की Code::Blocks में "Step
over" को "Next Line" कहा जाता ।
आइये ऊपर दिए गए program में Step
Over के असर
को देखें:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
void printValue(int nValue)
{
std::cout << nValue;
}
int main()
{
printValue(5);
return 0;
}
|
Program को तब तक "Step into" करते जाइये जब तक marker
printValue() को call करने वाले statement तक नहीं पहुँचता । कहने का
मतलब है, program को तब तक “Step into” करते जाइये, जब तक execute
होने
वाला अगला statement function printValue() को एक call ना हो ।

अब printValue() में , “Step into” की जगह "Step
over" select करें । अब debugger इस function
को execute
करेगा
(जिसके परिणाम स्वरुप console window पर 5 print
होगा)
और फिर अगले line में control आपको सौंप देगा (
return 0;) ।
Debugging करते वक़्त जब आपको पता हो की किसी function
में
कोई खराबी नहीं है, तो इसे छोड़कर आगे बढ़ने में Step over काफी उपयोगी साबित हो सकता है
।
Step out
ऊपर दिए गये दो stepping commands से अलग,
"Step out" केवल अगले line को execute
नहीं
करता । बल्कि, आप अभी जिस function में हो, “Step
out” उसके codes को भी execute
करता
है और जब function पूरी तरह से execute हो जाये, तो आपको control
सौंप
देता है ।
आइये इसका एक उदाहरण देखे:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
void printValue(int nValue)
{
std::cout << nValue;
}
int main()
{
printValue(5);
return 0;
}
|
जब तक आप printValue() में ना चले जाये,
program को
"Step into" करते जाइये ।


इसके बाद "Step out" चुन लीजिये । आप देखोगे की console
window पर 5 print
हो
चूका होगा, और function के ख़त्म होने के बाद debugger फिर से आपको control
सौंप
देगा ।
Run to cursor
जहाँ stepping out code के एक-एक line को रूक-रुक कर test करने में काफी उपयोगी है, किसी बड़े program
में, इन commands
का
इस्तेमाल करते हुए ज्यादा गहरायी से जाँच की आवश्यकता वाली जगह पर पहुंचना काफी
समय ले सकता है ।
हमारी किस्मत अच्छी है क्यूंकि modern
debuggers codes को अच्छी तरह से debug करने के लिए कुछ और tools प्रदान करते हैं।
इनमे से पहले command को Run to cursor के नाम से जाना जाता है । ये command, codes को तब तक normally execute करता है जब तक execution आपके cursor द्वारा selected code तक नहीं पहुँच जाता । इसके बाद ये आपको control return कर देता है, ताकि आप इसके आगे debugging का काम कर सके ।
इनमे से पहले command को Run to cursor के नाम से जाना जाता है । ये command, codes को तब तक normally execute करता है जब तक execution आपके cursor द्वारा selected code तक नहीं पहुँच जाता । इसके बाद ये आपको control return कर देता है, ताकि आप इसके आगे debugging का काम कर सके ।
आइये इसका भी एक उदाहरण देखें:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
#include <iostream>
void printValue(int nValue)
{
std::cout << nValue;
}
int main()
{
printValue(5);
return 0;
}
|
अपने cursor को printValue() function में line
std::cout << nValue; पर रखें, और इसके बाद right
click करके, यहाँ से "Run to
cursor" option चुन ले ।
आप देखोगे की arrow, जो execution
के
अगले line को दर्शाता है, वो आपके selected
line पर चला
जायेगा । अब debugger यहाँ से debug करने के लिए आपके commands
का
इंतज़ार कर रहा है ।
Run
जब आप किसी program को debug कर रहे होते हो, आप debugger
को program
के अंत
तक (या फिर अगले breakpoint तक, जिसके बारे में हम थोड़ी ही
देर में जानेंगे), run करने का instruction दे सकते हो । Visual
Studio 2005 Express में, इस command
को
"Continue" कहा जाता है । दुसरे IDEs में,
“Continue” की जगह "Run" या "Go"
शब्द
का इस्तेमाल किया जा सकता है ।
यदि आप ऊपर दिए गए examples को क्रमानुसार follow करते गए हो, तो आपको अभी function
printValue() में होना चाहिए । यहाँ से run command चुन लीजिये और आपका program
इसके
अंत तक execute होता चला जायेगा ।
Breakpoints
Breakpoint इस section का अंतिम topic है । Breakpoint एक ख़ास तरह का marker है, जो debug
mode active होने पर, debugger को breakpoint
की जगह
पर रूकने की आज्ञा देता है ।
Visual Studio 2005 Express में breakpoint
set करने
के लिए, Debug menu में जाकर "Toggle Breakpoint" को select कर ले (आप right
click कर Breakpoint
-> Insert Breakpoint भी चुन सकते हैं) ।

आगे बढ़ते हुए
std::cout << nValue; line
पर एक break
point set कीजिये
।
अब यहाँ से "Step into" select कर debugging
session की
शुरुआत कीजिये, और फिर debugger को program
के अंत
तक run करने के लिए “Continue” command का इस्तेमाल कीजिये । अब आप breakpoint
को
यहाँ काम करते हुए देख सकते हैं । आपको देखने को मिलेगा की program
को अंत
तक run करने के बजाय, debugger breakpoint की जगह पर रूक गया है !

Breakpoints code के किसी हिस्से को test करने करने में बहुत ज्यादा
उपयोगी हैं । आपको जहाँ भी code में गड़बड़ी का आभास होता है, वहाँ सबसे ऊपर बस एक breakpoint
set कर
दीजिये, यहाँ से debugger को run कीजिये, और debugger
अपने
आप breakpoint पर execution रोक कर आपको control
return कर
देगा । इसके बाद आप यहाँ से stepping commands का इस्तेमाल कर के अपने program
के
एक-एक line को run होते हुए देख सकते हो ।
एक आखरी note: अभी तक, हमने debugging
session start करने के लिए सिर्फ और सिर्फ "step
into" command का इस्तेमाल किया है । लेकिन debugger
को एक
ही बार में program के end तक run करने का instruction
भी
दिया जा सकता है । Visual Studio 2005 Express में, इसे Debug
menu में से
"Start debugging" option को चुनकर किया जा सकता है ।
दुसरे debuggers में भी ऐसे commands होते हैं, लेकिन इनके नाम अलग हो सकते
हैं । इनका उपयोग जब breakpoints के साथ किया जाता है, तो ये आपको code के उन हिस्सों, जहाँ गहरायी से जाँच-पड़ताल
की ज़रूरत है, में बहुत ही जल्द और commands लिखने के झंझट को कम करते हुए
पहुंचा देते हैं, ताकि आप यहाँ से आगे debug कर सके ।
निष्कर्ष
बधाई हो, अब आप debugging
के
सारे मुख्य तरीकों के बारे में जान चुके हो । इन commands
का
प्रयोग करके आप debugger को आसानी से अपने code में इस्तेमाल कर सकते हो ।
फिर भी, यहाँ debuggers के सिर्फ आधे फायदों का ज़िक्र किया गया है । अगले lesson में हम ये देखेंगे की debugging
के
दौरान किसी variable के value की जाँच कैसे की जाये । इसके
साथ-साथ हम कुछ अन्य information windows के बारे में भी जानेंगे जिनका
प्रयोग हम debugging के क्रम में अपनी सुविधा के लिए कर सकते हैं ।

No comments:
Post a Comment