[Học lập trình C++] Chương 1: 1.11a – Debugging chương trình của bạn (quan sát biến và call stack)
1.11a – Debugging chương trình của bạn (quan
sát biến và call stack)
Trong phần trước bạn
đã học làm sao sử dụng trình gỡ rối để quan sát quá trình thực hiện trong suốt
chương trình. Tuy nhiên, chạy từng bước chương trình của bạn chỉ là một nửa những
gì hữu ích của trình gỡ rối. Trình gỡ rối cũng để bạn quan sát giá trị của các
biến theo từng bước trong code của bạn.
Ví dụ của chúng ta ở
đây sẽ sử dụng trình gỡ rối của Visual Studio Express -- nếu bạn đang sử dụng
IDE/debugger khác, lệnh có thể khác tên hoặc nằm ở vị trí khác.
Quan sát các biến
Quan sát biến là một
quá trình xem xét kỹ giá trị của biến trong chương trình trong khi chương đang
thực thi trong chế độ gỡ rối. Hầu hết các trình gỡ rối cung cấp nhiều cách để
làm điều này. Hãy xem ví dụ sau:
#include "stdafx.h"
#include <iostream>
int main()
{
int x(1);
std::cout << x <<
" ";
x = x + 1;
std::cout << x << " ";
x = x + 2;
std::cout << x <<
" ";
x = x + 4;
std::cout << x << " ";
return 0;
}
Đây là một chương
trình dễ hiểu – nó in các giá trị 1, 2, 4, 8.
Đầu tiên sử dụng lệnh
“Run to cursor” để debug dòng đầu tiên std::cout << x << “ ”; :
Tại điểm này, biến x
đã được tạo và khởi tạo với giá trị 1, vì thế khi chúng ta kiểm tra giá trị của
biến x, chúng ta sẽ mong đợi nhận được giá trị 1.
Cách dễ nhất để kiểm
tra giá trị của biến đơn giống như x là di chuyển chuột vào biến x. Hầu hết
trình gỡ rối hiện tại đều hỗ trợ phương pháp này của việc xem giá trị của biến,
và đó là cách dễ hiểu nhất.
Chú ý rằng bạn có thể
xem giá trị của bất kì biến nào, không chỉ một dòng hiện tại.
Nếu bạn đang sử dụng
Visual Studio, bạn có thể sử dụng QuickWatch. Bôi đen biến x bằng chuột, và sau
đó chọn “QuickWatch” từ menu phải chuột.
Nó sẽ xuất hiện của sổ
chưa giá trị của biến:
Bây giờ hãy quan sát
biến này thay đổi khi chương trình chạy từng bước. Đầu tiên chọn “Step over”
hai lần, dòng kế tiếp được thực thi là std::cout << x << "
";
Biến x sẽ có giá trị
là 2. Quan sát kĩ và chắc chắn rằng nó có giá trị đó.
Cửa sổ quan sát
Sử dụng chuột hoặc
phương pháp QuickWatch để quan sát biến đều được nếu bạn muốn biến giá trị của
biến tại thời điểm cụ thể. Những nó sẽ không thích hợp để xem giá trị của một
biến thay đổi khi bạn chạy code bởi vì bạn tiếp tục phải di chuyển chuột vào hoặc
chọn lại giá trị đó.
Để giải quyết vấn đề
này, tất cả các trình biên dịch cung cấp một tính năng khác, gọi là cửa sổ quan
sát, của sổ quan sát là một của sổ mà bạn có thể thêm biến mà bạn muốn tiếp tục
quan sát, và những biến này sẽ được cập nhật khi qua mỗi bước mới của chương
trình. Của sổ quan sát có thể là màn hình hiển thị khi bạn đi vào chế độ debug,
nhưng nếu không, bạn có thể đưa nó ra ngoài IDE của bạn.
Trong Visual Studio
2005 Express, bạn vào Debug menu -> Windows -> Watch -> Watch 1 (chú ý:
Bạn phải ở trong chế độ debug, vào step into chương trình của bạn trước)
Bạn sẽ thấy như sau:
Không có gì trong cửa
sổ này bởi vì chúng ta chưa thiết lập. Thông thường có hai cách khác nhau để
thiết lập:
1) Gõ tên của tên biến bạn muốn xem trong cột
“Name” của của sổ quan sát.
2) Bôi đen biến mà bạn muốn quan sát, click phải
chuột và chọn “Add watch”.
Tiếp tục và thêm biến
x vào danh sách quan sát. Bạn sẽ nhìn thấy như sau:
Bây giờ chọn lệnh
“Step over” một vài lần và quan sát giá trị của biến của bạn thay đổi!
Chú ý rằng biến đó ra
khỏi scope (Ví dụ biến được khai báo trong một hàm, khi hàm đang chạy) sẽ ở
trong của sổ quan sát của bạn. Nếu biên trả về scop (ví dụ: hàm được gọi một lần
nữa), cửa sổ quan sát sẽ bắt đầu hiển thị giá trị của nó trở lại.
Sử dụng cửa sổ quan
sát là cách tốt nhất để quan sát giá trị của một biến thay đổi theo thời gian
khi bạn chạy chương trình từng bước.
Cửa sổ call stack
Trình gỡ rối hiện tại
chưa nhiều hơn một cửa sổ thông tin debugging và đó có thể rất hữu ích trong
debugging chương trình của bạn, và đó là call stack window.
Khi chương trình của
bạn gọi một hàm, bạn đã biết rằng nó đánh dấu vị trí hiện tại, thực hiện hàm và
sau đó trả về. Làm sau nó biết nơi nào để trả về? Câu trả lời là nó dựa vào
call stack.
Call tack là một danh
sách tất cả các hàm được kích hoạt mà được gọi để có được điểm thực thi hiện tại.
Call stack bao gồm điểm đi vào cho mỗi hàm, bao gồm những dòng đang được kích
hoạt. Bất cứ khi nào một hàm mới được gọi, hàm đó được thêm vào đỉnh của call
stack. Khi hàm hiện tại trả về cho trình gọi, nó bị xóa đi từ đỉnh của call
stack và điều khiển trả về cho hàm bên dưới nó.
Nếu bạn không thấy của
sổ call stack, bạn sẽ cần phải nói với IDE để hiển thị nó. Trong Visual Studio
2005 Express, bạn có thể thực hiện điều này bằng cách vào Debug Menu ->
Windows -> Call Stack (chú ý: bạn phải ở trong chế độ gỡ rối, vì vậy step
into chương trình của bạn trước).
Hãy quan sát call
stack sử dụng trong ví dụ sau:
#include "stdafx.h"
#include <iostream>
void CallC()
{
std::cout << "C called" << std::endl;
}
void CallB()
{
std::cout << "B called" << std::endl;
CallC();
}
void CallA()
{
CallB();
CallC();
}
int main()
{
CallA();
return 0;
}
Đặt một breakpoint
trong hàm CallC() và sau đó bắt đầu chế độ debugging. Chương trình sẽ thực cho
tới khi gặp dòng lệnh được đánh dấu là breakpoint.
Mặc dù bạn biết rằng
chương trình đang thực thi CallC(), thật ra có 2 lời gọi hàm CallC() trong
chương trình (một trong hàm CallB(), và một trong CallA()). Hàm nào chịu trách
nhiệm cho việc gọi CallC() thời điểm này? Call stack sẽ cho chúng ta thấy:
Chương trình bắt đầu
bằng việc gọi hàm main(). Main() gọi hàm CallA(), hàm đó gọi CallB(), hàm này gọi
hàm CallC(). Bạn có thể click đúp vào nhiều dòng trong cửa sổ Call stack để xem
nhiều thông tin về gọi hàm. Một vài IDEs giúp bạn gọi hàm một cách trực tiếp.
Khi bạn đã khôi phục lại code, click đúp vào dòng trên cùng của cửa sổ call
stack và bạn sẽ trả lại cho bạn điểm thực thi.
Nguồn: learn.cpp
Nhận xét
Đăng nhận xét