Xin chào và chào mừng.
Trong bài giảng này tôi muốn nói về gỡ lỗi.
Đây là một khái niệm rất quan trọng mà bạn cần hiểu cụ thể, bạn cần hiểu một số công
cụ và một số phương pháp mà bạn có thể sử dụng để tìm và sửa lỗi.
Vì vậy, gỡ lỗi là quá trình tìm và sửa lỗi trong một chương trình.
Thông thường lỗi logic.
Và tôi sẽ cho bạn biết sự khác biệt giữa lỗi logic và lỗi cú pháp, nhưng nó cũng có thể bao gồm lỗi cú pháp
của trình biên dịch.
Đó là toàn bộ quá trình cho các lỗi cú pháp.
Gỡ lỗi là hiểu những gì trình biên dịch đang nói với bạn.
Bạn luôn muốn tập trung khắc phục sự cố đầu tiên được phát hiện.
Tôi muốn điểm qua một số cảnh báo và lỗi phổ biến của trình biên dịch mà bạn có thể gặp phải, nhưng một
trong những điều bạn luôn muốn biết về trình biên dịch là trình biên dịch có thể đưa ra một
số lỗi cho bạn.
Bạn luôn muốn tập trung vào lỗi đầu tiên vì lỗi đầu tiên đó có thể dẫn đến các lỗi khác.
Vì vậy, có thể rất sai lầm nếu bạn thấy năm lỗi trong một chương trình mà trình biên dịch đang báo cho bạn, bạn có thể
chỉ mắc một lỗi và lỗi đầu tiên đó có thể gây ra các lỗi khác.
Vì vậy, điều quan trọng là luôn xem xét lỗi hàng đầu đầu tiên và sửa lỗi đó trước.
Trong ví dụ rất đơn giản này, chúng tôi có nhiều lỗi trong mã này.
Chúng tôi không có.
Chúng tôi không có dấu ngoặc nhọn bắt đầu bên trái, dấu ngoặc nhọn.
Chúng tôi không có dấu chấm phẩy.
Chúng tôi đang trả lại một chuỗi.
Và vì vậy khi chúng tôi lưu cái này và chúng tôi biên dịch nó và bạn thực sự thấy một số lỗi
màu đỏ, khi chúng tôi biên dịch nó, nó thực sự cho chúng tôi biết chúng tôi có ba lỗi.
Bạn không bao giờ muốn chỉ chọn lỗi cuối cùng ở dòng thứ bảy, mặc dù trong trường hợp này đó là một lỗi thực sự.
Bạn luôn muốn sửa lỗi đầu tiên.
Vì vậy, bạn thấy lỗi đầu tiên được liệt kê ở đây và bạn sửa lỗi đầu tiên đó, sau đó bạn biên dịch lại và chạy
lại.
Nhưng lý do để làm điều này chỉ để sửa lỗi cấp cao nhất đó là vì lỗi đó có thể gây ra các vấn
đề khác.
Vì vậy, hãy luôn tập trung vào việc sửa lỗi gỡ lỗi đầu tiên đó và quá trình tìm và sửa lỗi có thể rất
phức tạp từ việc tìm các lỗi đơn giản đến thu thập lượng lớn dữ liệu để phân tích.
Tất cả phụ thuộc vào.
Đôi khi bạn không có bất kỳ thông tin nào được cung cấp cùng với bạn ngoại trừ việc ghi nhật ký và trong trường hợp đó, bạn
phải phân tích mọi thứ.
Đôi khi bạn sẽ gặp lỗi không lặp lại được.
Bạn không thể sao chép nó vì nó xảy ra trong một dịp hiếm hoi như vậy.
Đó thường là khi bạn phải phân tích nhật ký hoặc một số biến thể của điều đó.
Khả năng gỡ lỗi của một lập trình viên là một kỹ năng cần thiết.
Đó thực sự là một kỹ năng giải quyết vấn đề có thể giúp bạn tiết kiệm rất nhiều thời gian và tiền bạc.
Vì vậy, nó là một kỹ năng quan trọng để học hỏi.
Đó là một kỹ năng quan trọng để phát triển.
Nó cần thực hành.
Bạn sẽ không đến với nó, nó sẽ không đến với bạn.
Có một số kỹ thuật nhất định mà bạn có thể áp dụng và các phương pháp mà bạn có thể áp dụng để giúp
bạn gỡ lỗi tốt hơn.
Tôi biết khá nhiều nhà phát triển thực sự giỏi viết mã phần mềm.
Họ hiểu ngôn ngữ rất tốt, nhưng kỹ năng sửa lỗi của họ rất kém.
Họ có thể gặp một lỗi và xu hướng đầu tiên của họ trong việc giải quyết lỗi đó thực sự là hơi lạc hướng.
Và một lần nữa, điều này đi kèm với thực hành.
Bạn sẽ ngày càng giỏi hơn trong việc gỡ lỗi và hiểu cách tìm và khắc phục sự cố, nhưng
đó cũng là điều bạn phải học.
Giai đoạn bảo trì là giai đoạn tốn kém nhất trong vòng đời phần mềm.
Giai đoạn bảo trì là sau khi bạn phát hành sản phẩm của mình và bây giờ bạn phải bảo trì nó.
Duy trì nó có nghĩa là sửa bất kỳ lỗi mới nào xuất hiện và cũng như thêm các tính năng mới.
Vì vậy, ví dụ: khi Windows phát hành một hệ điều hành mới chẳng hạn như Windows 10, họ vẫn chưa hoàn thành việc
sản xuất phần mềm đó.
Nó sẽ được đưa ra ngoài lĩnh vực này trong khoảng mười năm.
Và đó vẫn là trách nhiệm của Microsoft khi có bất kỳ lỗi mới nào xuất hiện hoặc họ tìm ra lỗi mới cho phần mềm đó để
sửa nó.
Và đó là lý do tại sao họ đẩy cập nhật tự động và họ làm những việc như vậy.
Và sau đó họ cũng sẽ nhận thấy rằng hệ điều hành sẽ đưa ra các tính năng mới khi thị trường thay đổi
và khi công nghệ thay đổi.
Vì vậy, bảo trì là rất quan trọng.
Do đó, việc tìm và sửa lỗi của bạn là rất quan trọng.
Tuy nhiên, hãy hiểu rằng lỗi là không thể tránh khỏi.
Tất cả các phần mềm đều có lỗi.
Không ai có thể viết mã hoàn hảo và thậm chí không nhất thiết phải viết mã hoàn hảo.
Chỉ là mọi thứ thay đổi theo thời gian.
Vì vậy, điều đó cũng có thể dẫn đến lỗi.
Bạn phải hiểu rằng chỉ vì phần mềm có lỗi không có nghĩa là mã được viết kém.
Đó là loại không thể tránh khỏi.
Vì vậy, bạn biết đấy, có lỗi cũng không sao, khi bạn tìm và sửa chúng, điều đó thậm chí còn tuyệt vời hơn vì bạn thực sự cảm thấy
như mình đang hoàn thành một điều gì đó.
Những vấn đề chung.
Và chúng ta sẽ nói thêm về các vấn đề cụ thể liên quan đến xem.
Nhưng các vấn đề phổ biến khi bạn đang cố gắng gỡ lỗi là các lỗi logic.
Các lỗi logic liên quan đến việc không ngược lại với loại lỗi cú pháp mà mã của bạn thực sự biên dịch.
Nó hoạt động, nhưng nó không làm những gì nó dự định làm.
Vì vậy, có một số loại logic hoặc chức năng dự định không chính xác.
Có thể bạn có một câu lệnh IF và bạn đang nhảy vào câu lệnh if đó với điều kiện sai.
Có thể bạn có một vòng lặp và vòng lặp không thực hiện đúng số lần hoặc bạn sắp xếp không chính
xác.
Chức năng bị hỏng, nhưng trình biên dịch nói, Này, mọi thứ đều ổn.
Đây là một ví dụ về lỗi logic.
Lỗi logic là khi cú pháp đúng, nhưng kết quả mong muốn không chính xác do một số loại vấn
đề logic.
Vì vậy, trong mã này, bạn thấy vòng lặp for có dấu chấm phẩy ở cuối đúng về mặt cú pháp.
Nhưng bạn đang mong đợi vòng lặp này chạy năm lần.
Nhưng không phải vậy.
Nó chỉ đi đến một thời gian chạy.
Vì vậy, nếu chúng tôi nói xây dựng và chúng tôi xây dựng dự án này, chúng tôi sẽ thấy một cảnh báo, điều này thật tuyệt và bạn phải luôn sửa tất cả các cảnh
báo của mình.
Nhưng nó đã biên dịch thành công.
Vì vậy, khi chúng tôi chạy dự án này, bạn sẽ nhận thấy rằng nó thực sự chỉ chạy một lần và in
ra Hello World một lần.
Vì vậy, đây là một ví dụ về lỗi logic.
Lỗi cú pháp liên quan trực tiếp đến trình biên dịch.
Đây là những điều không tuân theo các quy tắc của ngôn ngữ.
Bạn không có dấu chấm phẩy ở cuối câu lệnh.
Bạn không có một kết thúc, phải không?
Dấu ngoặc đơn trái, dấu ngoặc đơn.
Bạn đang thiếu một dấu ngoặc.
Bạn không sử dụng đúng từ khóa, đại loại như vậy.
Lỗi cú pháp thường do trình biên dịch gây ra. Lỗi logic sẽ do lập trình viên gây ra trong
giai đoạn thử nghiệm.
Tham nhũng bộ nhớ cũng là một vấn đề phổ biến, đặc biệt là trong C.
Nếu bạn không giải phóng bộ nhớ của mình sau khi phân bổ chính xác, bạn có
thể có những thứ như tài liệu tham khảo bị treo và bạn cũng có thể gặp sự cố bộ nhớ liên quan đến bộ nhớ không được sử dụng.
Bạn có thể bị rò rỉ bộ nhớ.
Đây là một ví dụ về lỗi bộ nhớ.
Trong mã cụ thể này, chúng tôi thực sự bị rò rỉ bộ nhớ, vì vậy chúng tôi chưa nói về con trỏ.
Chúng tôi chưa nói về cấp phát bộ nhớ động.
Nhưng trong C, bạn có thể cấp phát bộ nhớ trong khi chương trình của bạn đang chạy.
Bạn có thể sử dụng hàm malloc.
Và vì vậy ở đây chúng ta đang đánh dấu, chúng ta đang phân bổ bộ nhớ, nhưng chúng ta sẽ không bao giờ giải phóng nó.
Vì vậy, chúng tôi có thể xây dựng mã này và chúng tôi có thể chạy nó và mọi thứ đều ổn, nhưng chúng tôi không thực sự giải quyết được
lỗi này.
Vì vậy, những gì chúng tôi thực sự phải làm để sửa lỗi bộ nhớ này là chúng tôi phải nói miễn phí và sau đó chúng tôi phải
nói miễn phí và X để giải phóng con trỏ đó.
Nhưng bất cứ khi nào bạn phân bổ bộ nhớ, bạn sẽ không giải phóng nó.
Đó là rò rỉ bộ nhớ.
Và sau đó, một ví dụ khác là nếu chúng ta không phân bổ bộ nhớ, nếu chúng ta tạo một con trỏ và sau
đó cố gắng gán nó, chúng ta sẽ bị hỏng bộ nhớ vì bộ nhớ đó không có bất kỳ phân bổ nào cho nó và
chúng ta' đang cố gán giá trị cho nó.
Vì vậy, đó chỉ là một chút, mẩu tin nhỏ của một số ví dụ về bộ nhớ, lỗi, hiệu suất và khả năng mở rộng.
Đây có thể là sự cố trong đó chức năng của bạn được dự định như hiện tại và mã của bạn đúng về mặt cú
pháp, nhưng nó không hiệu quả lắm hoặc bạn không có phần cứng để hỗ trợ.
Vì vậy, nếu bạn đang chạy một máy chủ và bạn không có đủ phần cứng để hỗ trợ tất cả các yêu cầu,
thì nó sẽ chạy rất, rất chậm.
Hoặc nếu bạn viết chương trình của mình để làm việc với mười người dùng, nhưng khi chương trình có nhiều người dùng, có thể chương
trình không nhanh bằng vì cơ sở dữ liệu bị sa lầy hoặc bất kỳ trường hợp nào có thể xảy ra.
Mã hoạt động, nhưng nó không được thiết kế chính xác để xử lý nhiều, rất nhiều người dùng hoặc bất kỳ trường
hợp nào.
Thiếu sự gắn kết.
Đây có thể là một vấn đề trong mã của bạn làm giảm chất lượng liên quan đến mã của bạn đang hoạt động quá nhiều hoặc một chức năng
đang hoạt động quá nhiều.
Nó không phải là một tiêu điểm duy nhất hoặc thậm chí một ứng dụng có quá nhiều chức năng, có những tính
năng không bao giờ được sử dụng và vì vậy điều này có thể sẽ cần phải thiết kế lại.
Đây là một ví dụ về chương trình không được mô đun hóa, không gắn kết.
Bạn có một chức năng lớn đang thực hiện quá nhiều thứ với hàng trăm dòng mã, hàng nghìn
dòng mã.
Bạn muốn chia nhỏ một chức năng thành các chức năng trợ giúp, các mô-đun riêng biệt.
Điều đó làm cho chương trình của bạn gắn kết hơn, dễ bảo trì hơn.
Vì vậy, thay vì giống như một phương thức chính lớn thực hiện khởi tạo đọc đầu vào, tìm một
số, tìm sự khác biệt, tìm sản phẩm, tìm thương số, bạn có thể tạo tất cả mã này và đặt nó vào
các mô-đun trợ giúp và tách mã để việc phân tách có thể giúp tìm và sửa lỗi của bạn dễ dàng hơn nhiều.
Sự gắn kết luôn quan trọng trong C và nó thường được giải quyết khi bạn có sự gắn kết cao bằng cách cung cấp các phương
thức trợ giúp.
khớp nối chặt chẽ.
Điều này cũng phải làm với chất lượng của mã.
Đây là nơi bạn có rất nhiều phụ thuộc.
Khớp nối khác với sự gắn kết.
Sự gắn kết là trọng tâm duy nhất của bạn.
Khớp nối là nơi bạn có các phụ thuộc giữa các chức năng có thể hoặc giữa các đối tượng.
Chúng ta đã nói về khớp nối, chúng ta đã nói về các biến toàn cục.
Nếu một biến biến toàn cục đang được sử dụng trong nhiều chức năng khác nhau, nó có thể gây ra sự phụ thuộc
giữa các chức năng đó.
Vì vậy, điều bạn muốn phấn đấu khi viết mã và bạn đang viết mã chất lượng cao
là bạn muốn có sự gắn kết rất cao và sự liên kết rất thấp.
Quá trình gỡ lỗi.
Điều đầu tiên bạn phải làm trước khi có thể tìm và sửa bất kỳ lỗi nào là bạn phải
hiểu vấn đề.
Điều này có liên quan đến việc không chỉ đi sâu vào và bắt đầu xem mã, ngồi xuống với người kiểm tra,
hiểu các yêu cầu, hiểu những gì đang diễn ra.
Bởi vì nếu bạn không hiểu chuyện gì đang xảy ra, bạn thậm chí sẽ không thể hiểu được.
Bạn thậm chí không nên cố gắng giải quyết nó.
Khi bạn đã hiểu lỗi, hãy cố gắng sao chép nó vì việc sao chép lỗi có thể giúp bạn thu thập thêm
thông tin.
Không phải lúc nào cũng có thể tái tạo lỗi vì chúng có thể xảy ra trong những trường hợp rất hiếm.
Vì vậy, ví dụ: các lỗi giống như điều kiện chủng tộc hoặc thậm chí hỏng bộ nhớ chỉ có thể xảy ra trong một trường
hợp sử dụng rất cụ thể và chúng có thể là các sự cố không liên tục.
Và đó là trường hợp?
Và bạn không thể sao chép nó.
Nó sẽ trở nên ngày càng khó khăn hơn để gỡ lỗi.
Nếu bạn có thể sao chép nó, bạn thường có thể thu thập đủ thông tin để sửa nó.
Hầu hết các vấn đề đều có thể khắc phục được.
Ngoài ra, bạn có thể gặp sự cố không thể tái tạo sự cố nếu bạn đang ở trong môi trường đa luồng,
quy trình song song hoặc sự cố luồng.
Những lỗi đó cũng rất khó gỡ lỗi, nhưng chắc chắn hãy cố gắng tái tạo nó khi bạn
đã tìm ra vấn đề thực sự là gì về mặt bạn có thể hiểu được khi bạn có thể tái tạo, nếu không,
thì bạn muốn thử áp dụng một số kiểu phân chia và chinh phục.
Bạn muốn cố gắng cô lập lỗi, đơn giản hóa vấn đề, bởi vì khả năng rút gọn sẽ cung cấp cho bạn thông tin trở lại,
nhưng nó có thể không nhất thiết phải cho bạn biết lỗi nằm trong phần nào của mã.
Vì vậy, những gì bạn có thể làm để cố gắng đơn giản hóa vấn đề là loại bỏ các phần của trường hợp thử nghiệm ban đầu để bạn không
phải thử nghiệm quá nhiều.
Bạn có thể cô lập vấn đề thậm chí còn nhỏ hơn bằng cách nói, Ồ, nó chỉ xảy ra trong tình huống cụ thể này.
Bạn cũng có thể nhận xét mã.
Chúng tôi đã nói về các chức năng chỉ có sơ khai và không có triển khai.
Đôi khi điều đó được sử dụng trong thử nghiệm để có thể hạn chế vấn đề được đặt ra.
Ngoài ra, nếu bạn nhận xét mã, bạn sẽ có ít mã hơn mà lỗi thực sự có thể xảy ra.
Vì vậy, khi bạn đang nhận xét mã hoặc sao lưu các thay đổi, lỗi có thể biến mất và nếu lỗi biến mất, điều đó cho
bạn biết rằng mã mà bạn đã nhận xét có thể đã gây ra lỗi đó.
Tuy nhiên, về cơ bản, điều bạn muốn làm là biến một chương trình lớn thành nhiều chương trình nhỏ, thông
qua thử nghiệm hoặc nhận xét.
Một kỹ thuật phổ biến khác là có các bài kiểm tra đơn vị xung quanh mã của bạn.
Nếu kiểm tra đơn vị không thành công, điều đó có thể cho bạn biết chính xác logic hoặc vấn đề có thể nằm ở đâu trong mã của bạn.
Khi bạn cô lập lỗi, bạn và điều đó sẽ giúp bạn tìm ra nguồn gốc của sự cố trong mã,
mã cụ thể gây ra sự cố.
Đôi khi điều này sẽ sử dụng các công cụ sửa lỗi như trình gỡ lỗi.
Chúng ta sẽ nói cụ thể về trình gỡ lỗi, nhưng thường tùy thuộc vào loại phát triển tích hợp IDE mà bạn
sử dụng, sẽ có các trình gỡ lỗi đi kèm với IDE.
Ngoài ra còn có các trình gỡ lỗi có thể hạ cánh độc lập.
Trình sửa lỗi lớn quan trọng mà chúng ta sẽ sử dụng cho lập trình C được gọi là GDB.
Đó là trình sửa lỗi GNU, vì vậy nó là một công cụ tuyệt vời thực sự là một công cụ đồ họa nơi bạn có thể dừng việc
thực thi chương trình của mình và thêm vào các điểm dừng.
Và sau đó khi bạn dừng thực thi, bạn có thể đi từng dòng trong mã của mình và xem giá trị của các biến.
Vì vậy, bạn có thể thấy chính xác những gì đang diễn ra trong mã của mình khi mã đang chạy.
Đó là một công cụ vô giá.
Nó chỉ là nó rất hữu ích.
Chúng tôi sẽ chạy qua trình gỡ lỗi.
Tôi sẽ chỉ cho bạn cách thêm các điểm dừng.
Tôi sẽ chỉ cho bạn cách thiết lập đồng hồ để bạn có thể xem xét các biến khi chúng thay đổi và sau đó
xem qua mã.
Sau khi bạn đã xác định được nguồn gốc của vấn đề, bạn phải khắc phục nó.
Điều này cần rất nhiều kinh nghiệm và thực hành.
Chỉ vì bạn đã tìm ra nguồn gốc của vấn đề, bạn vẫn có thể không khắc phục được nếu chỉ dựa trên
kinh nghiệm của mình.
Điều này đôi khi bao gồm thiết kế lại hoặc tái cấu trúc mã khác, đặc biệt là với các vấn đề về khả năng mở rộng hoặc các
vấn đề về hiệu suất, bạn có thể phải thiết kế lại để cho phép phần mềm của mình có khả năng mở rộng hơn.
Vì vậy, không phải lúc nào cũng dễ dàng chỉ tìm ra vấn đề và sau đó khắc phục nó.
Đôi khi, sự cố, đặc biệt là các sự cố thậm chí còn khó hơn như phân luồng hoặc xử lý song song, những vấn
đề đó thậm chí còn khó khắc phục hơn.
Nhưng khi bạn viết ngày càng nhiều mã, điều này sẽ trở nên dễ thực hiện hơn.
Và cuối cùng, bạn phải kiểm tra như điên.
Luôn test thử nhiều ranh giới khác nhau.
Trường hợp tốt, trường hợp xấu ở giữa các trường hợp để xác minh rằng bạn đã thực sự khắc phục sự cố.
Một số kỹ thuật và công cụ có sẵn.
Một công cụ phổ biến và rất được sử dụng là sử dụng các câu lệnh in.
Bạn có thể sử dụng các câu lệnh in để theo dõi cơ bản mã của mình.
Vì vậy, trong C, bạn có thể sử dụng câu lệnh print F và bạn có thể đặt nó ở nhiều dòng trong mã của mình để biểu
thị vị trí của bạn.
Điều này cũng hữu ích, rất hữu ích khi chương trình của bạn bị treo.
Nó có thể giúp xác định nơi nó bị rơi.
Khi bạn thêm các câu lệnh in này theo dõi mã của mình, bạn có thể thêm đầu ra trong các câu lệnh
in để xem giá trị của các biến vì giá trị của các biến có thể ảnh hưởng đến trạng thái và có thể
gây ra các vấn đề logic.
Vì vậy, chỉ cần thêm các câu lệnh in là rất, rất hữu ích.
Nó có thể hiển thị luồng thực thi và nó có thể giúp cô lập lỗi.
Trình gỡ lỗi như tôi đã đề cập trong GDB, những trình gỡ lỗi này có thể giám sát việc thực thi chương trình.
Bạn có thể dừng nó, bạn có thể chạy từng dòng một, khởi động lại nó, đặt các điểm dừng, xem các biến và bộ nhớ.
Rất, rất hữu ích khi cố gắng chẩn đoán vấn đề nằm ở đâu.
Tệp nhật ký.
Các tệp nhật ký cũng rất hữu ích, đặc biệt đối với các lỗi không thể tạo lại.
Bạn có thể phân tích chúng vào một ngày sau đó để xem chính xác điều gì đang xảy ra khi lỗi xảy ra.
Vì vậy, điều này có nghĩa là bạn phải cung cấp các báo cáo ghi nhật ký tốt trong chính mã của mình để
điều này trở nên hữu ích.
Vì vậy, bạn có thể tạo tệp nhật ký của riêng mình và sau đó ghi vào nhật ký đó khi chương trình đang chạy để nếu bạn gặp lỗi,
bạn có thể gửi các nhật ký đó cho nhà phát triển.
Chúng tôi sử dụng điều này khá nhiều tại Xerox vì khi gặp sự cố, không phải lúc nào chúng tôi cũng có thể tái tạo chúng hoặc chúng
có thể gặp phải tại hiện trường.
Chúng tôi cần có thể truy cập các nhật ký đó để xem điều gì đang xảy ra khi lỗi đó xảy ra.
Phần mềm giám sát.
Có phần mềm có thể giám sát và phân tích thời gian chạy về việc sử dụng bộ nhớ, mối đe dọa lưu lượng mạng và
thông tin đối tượng.
Điều này có thể cho bạn biết nếu có thể bạn đang phân bổ quá nhiều bộ nhớ và không xóa nó.
Nếu bạn có một công cụ cho lưu lượng truy cập mạng sử dụng bộ nhớ có thể cho bạn biết liệu bạn có đang gửi quá
nhiều gói hay không hoặc liệu phần mềm của bạn có thể mở rộng hay không, nếu bạn có lưu lượng truy cập mạng
tăng lên và bạn thấy rằng phản hồi của bạn thời gian đang xuống cấp.
Bạn cũng có thể theo dõi thông tin về luồng và đối tượng để xử lý song song để xem điều gì đang diễn ra trong một số luồng nhất
định và điều gì đang diễn ra trong luồng khác.
Điều đó sẽ giúp bạn chẩn đoán bất kỳ loại vấn đề nào.
Một số công cụ sửa lỗi phổ biến khác mà bạn có thể sử dụng để tìm và sửa lỗi của mình.
Bạn có thể sử dụng xử lý ngoại lệ.
Nhiều ngôn ngữ lập trình có xử lý ngoại lệ.
Thật không may, C không phải là trình xử lý ngoại lệ thực sự sẽ ngăn chặn sự cố và thực hiện nhiều việc trong thời
gian chạy.
Nó không áp dụng để xem, nhưng nó vẫn là một điều tốt để hiểu.
Các khối Trycatch, những thứ tương tự.
Máy phân tích tĩnh.
Có nhiều máy phân tích tĩnh có sẵn cho máy phân tích tĩnh C.
Phân tích mã nguồn mà không có tệp thực thi thực tế.
Chạy chương trình không cần chạy.
Nó đi từng dòng một và nhìn vào mã nguồn.
Và khi phân tích cú pháp mã nguồn, nó sẽ tìm mọi sự cố đã biết.
Vì vậy, nó có thể kiểm tra ngữ nghĩa.
Nó có thể chắc chắn rằng.
Đó là nó.
Bạn không có bất kỳ biến chưa được khởi tạo nào nếu bạn đang phân bổ bộ nhớ mới mà bạn xóa
nó.
Nếu bạn có bất kỳ mã chết nào mà mã không thực sự được thực thi, bạn có thể xóa mã đó.
Nó cũng phân tích những thứ như điều kiện chủng tộc và bế tắc.
Chúng tôi sử dụng một vài máy phân tích tĩnh nơi tôi làm việc.
Chúng tôi có một công cụ tên là Coverity, công cụ này khá phổ biến và cũng có một công cụ sonar mã mà chúng tôi sử dụng, và chúng tôi sẽ chạy
công cụ này trên toàn bộ đường cơ sở, toàn bộ bộ nguồn của chúng tôi.
Và bất cứ khi nào chúng tôi giới thiệu các tệp mới và mã mới, công cụ đó sẽ chạy trên mã đó và sẽ có thể xác
định các vấn đề ngay lập tức với mã cho đến các biến chưa được khởi tạo, rò rỉ bộ nhớ, v.v.
Nó không phân tích cú pháp.
Đó là những gì trình biên dịch dành cho.
Ngoài ra còn có một số bộ thử nghiệm chạy một tập hợp các thử nghiệm toàn diện từ đầu đến cuối của hệ thống mà bạn có thể
chạy trên phần mềm của mình.
Thử nghiệm luôn quan trọng, nhưng nếu bạn có thể tự động hóa nó bằng cách nào đó để chạy một số thử nghiệm nhất định
mỗi khi bạn thực hiện một bản dựng mới, chẳng hạn, điều đó có thể rất hữu ích và điều này thực sự có thể
ngăn ngừa lỗi, đồng thời cũng giúp chẩn đoán lỗi.
Gỡ lỗi chương trình sau khi nó bị lỗi.
Chúng ta sẽ nói về một thứ gọi là ngăn xếp cuộc gọi.
Đây là một cơ chế rất hữu ích để xem, đặc biệt là trong ngôn ngữ như C, nơi bạn gặp sự cố và tất cả thông
tin duy nhất mà bạn nhận được là lỗi phân đoạn.
Khi bạn gặp sự cố đó, điều gì sẽ xảy ra rất nhiều lần, tùy thuộc vào cách nó gặp sự cố, một tệp lõi
sẽ được tạo và bạn có thể phân tích tệp lõi để xem ngăn xếp cuộc gọi để biết chính xác nơi chương trình đó
đã chết.
Nó sẽ cho bạn biết dòng mã mà chương trình đã chết.
Và vì vậy chúng ta sẽ tìm hiểu về ngăn xếp cuộc gọi.
Và khi phân tích các tệp cốt lõi, đó là một kỹ thuật nâng cao hơn.
Nhưng trong C, một tệp cốt lõi có thể được tạo và bạn có thể phân tích nó.
Đó là một kỹ thuật nâng cao hơn một chút, nhưng đó là một cách khác mà bạn có thể thực hiện gỡ lỗi trên phần mềm của mình.
Điều gì về việc ngăn ngừa lỗi?
Chúng tôi biết rằng gỡ lỗi là tìm và sửa lỗi nhưng nếu bạn có thể ngăn ngừa lỗi thì điều đó còn tốt hơn nữa.
Một trong những cách bạn có thể ngăn ngừa lỗi là bạn có thể viết mã chất lượng cao.
Đây thực sự không phải là trọng tâm của nhiều kỹ sư phần mềm.
Rất nhiều kỹ sư phần mềm viết mã, và miễn là nó hoạt động, đó là tất
cả những gì họ quan tâm hoặc miễn là đầu ra đúng, thì họ coi như xong.
Nhưng có một thứ gọi là mã kém chất lượng và bạn không muốn viết nó.
Tôi đã trình bày một số điều này trong các bài giảng, nhưng những việc như sử dụng tên biến có ý nghĩa
là rất quan trọng.
Hoặc nếu bạn viết mã không hiệu quả khi bạn đang sử dụng các vòng lặp có thể nhiều hơn mức cần thiết hoặc sử dụng câu lệnh
if hoặc bạn không cần phải làm điều đó.
Tất cả những thứ này tạo thành mã kém chất lượng.
Nếu bạn có một chức năng đang thực hiện 100 việc khác và nó không gắn kết, nếu bạn có 5000 dòng trong
một chức năng, nếu mã của bạn không được tổ chức theo kiểu mô-đun hoặc nếu bạn có nhiều phụ
thuộc giữa các chức năng, thì tất cả những điều này đều kém mã chất lượng và bạn muốn cố gắng không làm điều này.
Bạn muốn sử dụng các kỹ thuật mà chương trình của bạn được tổ chức.
Nó dễ bảo trì, nó có tính gắn kết cao, nó có khả năng ghép nối thấp và bạn sử dụng các tên biến có
ý nghĩa.
Rất rất quan trọng.
Một lần nữa, nó cũng rất quan trọng bởi vì giai đoạn bảo trì rất tốn kém.
Nếu bạn viết mã kém chất lượng, việc bảo trì sẽ trở nên khó khăn hơn nhiều.
Việc tách lỗi khó hơn và khó thêm các tính năng mới hơn.
Vì vậy, các kỹ thuật chất lượng cao của nhân viên khi viết mã của bạn.
Bài kiểm tra đơn vị.
Các bài kiểm tra đơn vị giúp ngăn ngừa lỗi rất nhiều.
Các bài kiểm tra đơn vị thường được thực thi tự động khi bạn biên dịch các bài kiểm tra đơn vị có thể giúp tránh hồi quy.
Đó là một trong những yếu tố quan trọng nhất.
Hồi quy là khi bạn viết mã mới và bạn đưa ra một lỗi trên thứ gì đó đã hoạt động trước đó.
Bạn đã phá vỡ mã cũ.
Bạn không muốn làm điều đó.
Nếu một số phần mềm đang hoạt động và sau đó một phần mềm mới nào đó mà bạn đã làm hỏng nó, thì bạn muốn được thông báo ngay
lập tức và các bài kiểm tra đơn vị có thể giúp làm điều đó bởi vì các bài kiểm tra đơn vị sẽ chạy trên mã cũ đó và nó sẽ thông báo, Này, cái
này đã hoạt động, bây giờ nó đã ổn thất bại.
Nó cũng có thể tìm thấy lỗi trong mã mới trước khi nó được phân phối, bởi vì một lần nữa, chúng chạy sau khi bạn xây dựng và nó
sẽ ngay lập tức cho bạn biết có gì đó không ổn.
Có một khái niệm về phát triển dựa trên thử nghiệm đang trở nên thực sự rất phổ biến.
Đây là nơi bạn viết bài kiểm tra trước và sau đó bạn phát triển mã của mình.
Và mục tiêu ở đây là khi bạn viết bài kiểm tra đầu tiên của mình, bài kiểm tra của bạn bị lỗi và sau đó bạn viết
mã để nó vượt qua.
Có rất nhiều lợi thế đối với TDD và đó là một cách suy nghĩ ngược lại.
Thông thường mọi người khi họ viết mã, họ viết mã trước và sau đó viết bài kiểm tra sau.
Nhưng với TDD, nó thực sự mang đến cho bạn một cách suy nghĩ khác để bạn đang làm việc trong
những phần thực sự nhỏ và bạn có xu hướng viết mã rất gắn kết và bạn không có mã, không
có nhiều phụ thuộc vì đoán. Gì?
Nếu bạn có thể kiểm tra mã, điều đó có nghĩa là mã không có nhiều phần phụ thuộc.
Nếu bài kiểm tra đơn vị của bạn thực sự rất lớn và bạn đang chế nhạo tất cả những thứ khác nhau này,
thì đó thường là một dấu hiệu lớn cho thấy mã của bạn rất, rất phụ thuộc vào những thứ khác.
Vì vậy, bằng cách sử dụng TDD, nó buộc bạn phải viết mã được ghép nối rất lỏng lẻo, không có phần phụ thuộc và nó buộc
bạn phải có các chức năng của mình thật gắn kết.
Có rất nhiều lợi thế của TDD.
Bạn cũng muốn cung cấp tài liệu tốt và bạn muốn lập kế hoạch phù hợp.
Đừng chỉ đi sâu vào mã và bắt đầu triển khai.
Viết ra thiết kế của bạn trên giấy.
Sử dụng mã giả.
Phải.
Lập kế hoạch mã của bạn.
Nếu bạn lập kế hoạch mã của mình, bạn hiểu các yêu cầu và bạn có một thiết kế chu đáo, bạn có
thể ngăn ngừa rất nhiều lỗi.
Và tôi đã đề cập đến điều này trong suốt khóa học, nhưng điều rất, rất quan trọng là phải
có cách tiếp cận kiểu chia để trị, làm việc theo từng bước nhỏ và liên tục kiểm tra sau mỗi bước, đừng viết 1000 dòng mã
và sau đó nói, được, hãy biên dịch và kiểm tra.
Đó không phải là một cách tiếp cận tốt.
Tránh thay đổi quá nhiều cùng một lúc.
Khi thực hiện các thay đổi, hãy áp dụng chúng dần dần, thêm một thay đổi, sau đó kiểm tra kỹ lưỡng trước khi bắt đầu
bước tiếp theo.
Điều này có thể giúp giảm tất cả các loại lỗi và nó cũng hạn chế nhóm vấn đề của bạn.
Vì vậy, nếu bạn có một lỗi, bạn sẽ ngay lập tức biết nó nằm ở đâu trong mã vì bạn vừa
biên dịch và bạn vừa thêm dòng hoặc số dòng đó.
Một lần nữa, tôi không thể nhấn mạnh tầm quan trọng của việc gỡ lỗi viết mã chất lượng cao, ngăn ngừa lỗi.
Những kỹ thuật giải quyết vấn đề này sẽ giúp bạn tiết kiệm rất nhiều thời gian và giúp bạn trở thành một lập trình viên hàng đầu
giỏi hơn nhiều.
Vì vậy, trong vài bài giảng tiếp theo, tôi muốn nói về một số lỗi phổ biến mà chúng ta thấy trong ngôn ngữ lập
trình c c.
Ngoài ra, tôi muốn nói một chút về ngăn xếp cuộc gọi.
Tôi muốn xem qua trình gỡ lỗi giới thiệu cho bạn các tùy chọn menu và cách bạn có thể dừng và
chạy đồng hồ, v.v.
Và tôi cũng muốn giúp xác định một số lỗi phổ biến của trình biên dịch mà bạn thấy cách diễn giải các trình biên dịch, các cảnh báo và lỗi
của trình biên dịch.
Điều đó có nghĩa là gì nếu trình biên dịch nói điều này?
Điều đó có nghĩa là gì nếu trình biên dịch đưa ra cảnh báo này cho bạn?
Cảm ơn.