DOUG LLOYD: Tất cả các quyền GDB. Đó là chính xác những gì? Vì vậy, GDB, viết tắt cho GNU Debugger, là một công cụ thực sự tuyệt vời mà chúng ta có thể sử dụng để giúp chúng tôi gỡ lỗi chương trình của chúng tôi, hoặc tìm ra nơi mà mọi thứ đi sai trong các chương trình của chúng tôi. GDB là rất mạnh, nhưng đầu ra và tương tác với nó có thể là một chút khó hiểu. Nó thường là một công cụ dòng lệnh, và nó có thể ném rất nhiều tin nhắn vào bạn. Và nó có thể loại khó phân tích chính xác những gì đang xảy ra. Bước May mắn thay, chúng tôi đã thực hiện để khắc phục vấn đề này cho bạn khi bạn làm việc thông qua CS50. Nếu bạn không sử dụng các đồ họa gỡ rối, mà đồng nghiệp của tôi Dan Armandarse đã nói khá một chút về trong một video nên chấm dứt tại đây ngay bây giờ, bạn có thể cần để sử dụng các dòng lệnh các công cụ để làm việc với GDB. Nếu bạn đang làm việc trong các CS50 IDE, bạn không cần phải làm điều này. Nhưng nếu bạn không làm việc trong các CS50 IDE, có lẽ sử dụng một phiên bản của CS50 gia dụng, hoặc hoạt động khác Linux hệ thống với GDB cài đặt trên nó, bạn có thể cần phải sử dụng các công cụ dòng lệnh. Và vì có lẽ bạn phải làm điều đó, nó hữu ích chỉ để hiểu làm thế nào GDB hoạt động từ dòng lệnh. Nhưng một lần nữa, nếu bạn sử dụng các IDE CS50, bạn có thể sử dụng các trình sửa lỗi đồ họa được xây dựng vào IDE. Vì vậy, để có được những thứ đi với GDB, để bắt đầu gỡ lỗi quá trình của một cụ thể chương trình, tất cả các bạn cần làm được gõ GDB tiếp bởi tên chương trình. Vì vậy, ví dụ, nếu chương trình của bạn hello, bạn nên gõ GDB hello. Khi bạn làm điều đó, bạn sẽ để kéo lên môi trường GDB. Nhắc nhở của bạn sẽ thay đổi, và thay vì những gì nó thường là khi bạn gõ những thứ ở ls line-- lệnh, cd-- tất cả các đặc trưng của bạn Lệnh Linux, nhắc nhở của bạn sẽ thay đổi đến, có lẽ, một cái gì đó như dấu ngoặc đơn ngoặc GDB. Đó là GDB nhắc mới của bạn, bởi vì bạn đang ở trong môi trường GDB. Một khi bên trong của môi trường đó, có hai lệnh chính có thể bạn sẽ sử dụng theo thứ tự sau đây. Đầu tiên là b, là ngắn cho nghỉ. Và sau khi bạn gõ b, bạn thường gõ tên của một hàm, hoặc nếu bạn xảy ra để biết xung quanh những gì dòng số chương trình của bạn được bắt đầu cư xử một chút lạ, bạn có thể gõ một dòng số đó là tốt. B gì, hoặc nghỉ ngơi, không là nó cho phép chương trình của bạn để chạy cho đến một điểm nhất định, cụ thể là, tên của chức năng mà bạn chỉ định hoặc dòng số mà bạn chỉ định. Và tại thời điểm đó, nó sẽ đóng băng thực hiện. Đây là một điều thực sự tốt, bởi vì khi thực hiện đã được đông lạnh, bạn có thể bắt đầu rất chậm bước qua chương trình của bạn. Thông thường, nếu bạn đã chạy chương trình của bạn, chúng rất ngắn. Thông thường, bạn gõ dấu chấm dấu gạch chéo bất cứ điều gì tên của chương trình của bạn, nhấn Enter, và trước khi bạn có thể nhấp nháy, bạn Chương trình đã được hoàn thành. Nó không thực sự có rất nhiều thời gian để thử và tìm ra những gì đang xảy ra sai. Vì vậy, nó thực sự để có thể chậm điều xuống bằng cách thiết lập một điểm break với b, và sau đó bước vào. Sau đó, một khi bạn đã thiết lập nghỉ của bạn điểm, bạn có thể chạy chương trình. Và nếu bạn có bất kỳ đối số dòng lệnh, bạn chỉ định cho họ ở đây, không phải khi bạn gõ GDB tên chương trình của bạn. Bạn chỉ rõ tất cả các dòng lệnh đối số bằng cách lấy r, hoặc chạy, và sau đó đối số dòng lệnh bất cứ điều gì bạn cần bên trong của chương trình của bạn. Có một số khác thực sự lệnh quan trọng và hữu ích bên trong của môi trường GDP. Vì vậy, hãy để tôi một cách nhanh chóng đi qua một số trong số họ. Đầu tiên là n, mà là viết tắt tiếp theo, và bạn có thể gõ tiếp theo thay vì n, cả hai sẽ làm việc. Và nó chỉ là viết tắt. Và như bạn đã có thể đã nhận sử dụng để, để có thể gõ những thứ ngắn hơn nói chung là tốt. Và những gì nó sẽ làm điều đó là sẽ bước về phía trước một khối mã. Vì vậy, nó sẽ di chuyển về phía trước cho đến khi một cuộc gọi chức năng. Và sau đó thay vì lặn vào chức năng mà và đi qua tất cả các chức năng mà code, nó sẽ chỉ có các chức năng. Các chức năng sẽ được gọi. Nó sẽ làm bất cứ điều gì công việc của mình là. Nó sẽ trả về một giá trị cho hàm nào đã gọi nó. Và sau đó bạn sẽ chuyển sang dòng tiếp theo đó chức năng gọi điện thoại. Nếu bạn muốn bước bên trong của các chức năng, thay vì chỉ có nó thực hiện, đặc biệt là nếu bạn nghĩ rằng vấn đề có thể nằm bên trong hàm đó, bạn có thể, tất nhiên, thiết lập ngắt trỏ bên trong hàm đó. Hoặc nếu bạn đang chạy, bạn có thể sử dụng s để bước về phía trước một dòng mã. Vì vậy, đây sẽ bước vào và bổ nhào vào chức năng, thay vì chỉ có thực thi và tiếp tục trong các chức năng rằng bạn đang ở để gỡ lỗi. Nếu bạn đã bao giờ muốn biết giá trị của một biến, bạn có thể gõ p, hay Print, và sau đó là tên biến. Và đó sẽ in ra cho bạn, bên trong của môi trường GDB, tên của các biến, mà you-- tha me-- giá trị của biến mà bạn đã đặt tên. Nếu bạn muốn biết giá trị của mỗi biến thể truy cập địa phương từ nơi bạn hiện đang ở trong bạn chương trình, bạn có thể gõ info người dân địa phương. Nó nhanh hơn rất nhiều so với gõ p và sau đó bất cứ điều gì, liệt kê ra tất cả các biến mà bạn biết tồn tại. Bạn có thể gõ info người dân địa phương, và nó sẽ in ra tất cả mọi thứ cho bạn. Tiếp theo là bt, đó là ngắn để lại dấu vết. Bây giờ, nói chung, đặc biệt là vào đầu năm CS50, bạn sẽ không thực sự có dịp sử dụng bt, hoặc Back Trace, bởi vì bạn không có chức năng mà gọi các chức năng khác. Bạn có thể có một cuộc gọi chính chức năng, nhưng đó có lẽ nó. Bạn không cần phải có chức năng khác gọi một chức năng, trong đó gọi hàm khác, và như vậy. Nhưng như các chương trình của bạn nhận được nhiều hơn phức tạp, và đặc biệt khi bạn bắt đầu làm việc với đệ quy, lại dấu vết có thể là một cách thực sự hữu ích cho bạn loại có được một số bối cảnh cho nơi Tôi đang ở trong chương trình của tôi. Vì vậy, nói rằng bạn đã viết mã của bạn, và Bạn có biết rằng chính các cuộc gọi một chức năng f, trong đó kêu gọi một chức năng g, trong đó kêu gọi một hàm h. Vì vậy, chúng tôi có một số lớp Nesting xảy ra ở đây. Nếu bạn đang ở trong các môi trường GDB của bạn, và bạn biết bên trong của bạn của h, nhưng lại quên về những gì có bạn đến nơi mà bạn are-- bạn có thể gõ bt, hay lại dấu vết, và nó sẽ in ra h, g, f chính, cùng với một số thông tin khác, mà cung cấp cho bạn một đầu mối rằng, OK chính gọi là f, f gọi là g, g gọi là h, và đó là nơi tôi hiện đang trong chương trình của tôi. Vì vậy, nó có thể được thực sự hữu ích, đặc biệt là khó hiểu-Ness của GDB trở thành một chút áp đảo, để tìm ra chính xác nơi mà mọi thứ đang có. Cuối cùng, khi chương trình của bạn được thực hiện, hoặc khi bạn đang thực hiện gỡ nó và bạn muốn bước đi từ môi trường GDB, nó giúp để biết làm thế nào để có được ra khỏi nó. Bạn có thể gõ q, hoặc Quit, để nhận ra. Bây giờ, trước khi video hiện nay Tôi đã chuẩn bị một chương trình buggy gọi buggy1, mà tôi biên soạn từ một tập tin gọi là buggy1.c. Như bạn có thể mong đợi, điều này chương trình là trong thực tế lỗi. Có điều gì sai khi tôi cố gắng và chạy nó. Bây giờ, thật không may, tôi vô tình xóa file buggy1.c của tôi, vì vậy để cho tôi để tìm ra những gì đang xảy ra sai với chương trình này, Tôi sẽ phải sử dụng GDB loại một cách mù quáng, cố gắng để điều hướng thông qua chương trình này để tìm ra chính xác những gì đang xảy ra sai. Nhưng chỉ sử dụng các công cụ chúng ta đã học về, chúng ta có thể khá nhiều con số ra đó là chính xác những gì. Vì vậy, hãy đi qua để CS50 IDE và có một cái nhìn. OK, vì vậy chúng ta ở đây trong tôi CS50 môi trường IDE, và tôi sẽ phóng to một chút vì vậy bạn có thể nhìn thấy nhiều hơn một chút. Trong cửa sổ thiết bị đầu cuối của tôi, nếu tôi liệt kê các nội dung của giám đốc hiện tại của tôi với ls, chúng ta sẽ thấy rằng tôi có một vài tập tin nguồn ở đây, bao gồm cả các thảo luận trước buggy1. Chính xác những gì đi vào khi Tôi cố gắng và chạy buggy1. Vâng chúng ta hãy cùng tìm hiểu. Tôi gõ dấu chấm dấu gạch chéo, lỗi, và tôi nhấn Enter. Lỗi phân khúc. Đó không phải là tốt. Nếu bạn nhớ lại, một lỗi segmentation thường xảy ra khi chúng ta truy cập vào bộ nhớ rằng chúng tôi không được phép chạm vào. Chúng tôi đã bằng cách nào đó đạt bên ngoài các giới hạn về những gì các chương trình, trình biên dịch, đã cho chúng ta. Và như vậy đã là một đầu mối để giữ trong hộp công cụ khi chúng tôi bắt đầu quá trình gỡ lỗi. Một cái gì đó đã đi một chút sai ở đây. Được rồi, vậy chúng ta hãy bắt đầu lập môi trường GDB và xem chúng ta có thể tìm ra những gì chính xác vấn đề là. Tôi sẽ để xóa màn hình của tôi, và tôi sẽ gõ GDB một lần nữa, để vào môi trường GDB, và tên của chương trình mà tôi muốn gỡ lỗi, buggy1. Chúng tôi nhận được một tin nhắn nhỏ, đọc biểu tượng từ buggy1, thực hiện. Tất cả điều đó có nghĩa là nó kéo cùng tất cả các mã, và bây giờ nó được nạp vào GDB, và nó sẵn sàng để đi. Bây giờ, những gì tôi muốn làm gì? Bạn có nhớ lại những gì Bước đầu tiên thường là sau khi tôi là bên trong của môi trường này? Hy vọng rằng, các bạn nói đặt một điểm break, vì trong thực tế, đó là những gì tôi muốn làm. Bây giờ, tôi không có mã nguồn cho điều này trước mặt tôi, mà có lẽ là không phải là trường hợp điển hình sử dụng, bằng cách này. Bạn có lẽ sẽ. Vì vậy, đó là tốt. Nhưng giả sử bạn không, những gì một trong những chức năng mà bạn biết tồn tại trong mọi chương trình C đơn? Không có vấn đề lớn như thế nào hoặc làm thế nào phức tạp đó là, chức năng này chắc chắn tồn tại. Chính, phải không? Vì vậy, không hết, chúng ta có thể thiết lập một điểm break ở chinh. Và một lần nữa, tôi chỉ có thể gõ phá vỡ chính, thay vì b. Và nếu bạn đang tò mò, nếu bạn từng loại ra một lệnh dài và sau đó nhận ra rằng bạn gõ sai việc gì, và bạn muốn được thoát khỏi của tất cả như tôi vừa làm, bạn có thể mất kiểm soát U, mà sẽ xóa tất cả mọi thứ và đưa bạn trở lại đến đầu của các dòng con trỏ. A nhanh hơn rất nhiều hơn là chỉ giữ xóa, hoặc đánh nó một lần bó trên. Vì vậy, chúng tôi sẽ thiết lập một điểm break ở chinh. Và như bạn thấy, nó nói rằng chúng ta đã thiết lập một điểm break ở tập buggy1.c, và dường như các dòng đầu tiên mã của chính là dòng bảy. Một lần nữa, chúng tôi không có các tập tin nguồn ở đây, nhưng tôi sẽ giả định rằng đó là nói thật. Và sau đó, tôi chỉ cố gắng và chạy chương trình, r. Bắt đầu chương trình. Tất cả các quyền, vì vậy thông điệp này là một chút khó hiểu. Nhưng về cơ bản những gì xảy ra ở đây là nó chỉ nói với tôi rằng tôi đã trúng giải lao của tôi điểm, điểm break số 1. Và sau đó, rằng dòng mã, không có tập tin hoặc thư mục. Lý do duy nhất mà Tôi nhìn thấy tin nhắn đó là vì tôi vô tình xóa file buggy.c của tôi. Nếu tập tin buggy1.c tôi tồn tại trong thư mục hiện hành, mà đúng tuyến có thực sự sẽ cho tôi biết những gì các dòng mã nghĩa đen lần đọc. Thật không may, tôi đã xóa nó. Chúng ta sẽ phải loại điều hướng thông qua điều này một chút mù quáng hơn. OK, vì vậy hãy xem, những gì Tôi muốn làm ở đây? Vâng, tôi muốn biết những gì địa phương các biến thể có sẵn cho tôi. Tôi đã bắt đầu chương trình của tôi. Chúng ta hãy xem những gì có thể được khởi tạo cho chúng ta. Tôi gõ Thông tin người dân địa phương, không có người dân địa phương. Tất cả các quyền, do đó không cho tôi một tấn thông tin. Tôi có thể thử và in ra một biến, nhưng tôi không biết bất cứ tên biến. Tôi có thể thử một dấu vết trở lại, nhưng tôi là bên trong của chính, vì vậy tôi biết tôi đã không được thực hiện một cuộc gọi chức năng ngay bây giờ. Vì vậy, có vẻ như lựa chọn duy nhất của tôi là sử dụng n hay như vậy và bắt đầu nhảy vào. Tôi sẽ sử dụng n. Vì vậy, tôi gõ n. Ôi chúa ơi, những gì đang xảy ra ở đây. Chương trình đã nhận được tín hiệu, SIGSEGV lỗi phân khúc, và sau đó một bó toàn bộ các công cụ. Tôi đã bị choáng ngợp. Vâng, có thực sự là một rất nhiều để được học ở đây. Vì vậy, điều này cho chúng ta biết? Những gì nó nói với chúng ta là, chương trình này là về đến, nhưng có chưa, lỗi seg. Và đặc biệt, tôi sẽ để phóng to hơn nữa ở đây, nó về để seg lỗi về một cái gì đó gọi là strcmp. Bây giờ, chúng ta có thể không có thảo luận Chức năng này rộng rãi. Nhưng nó is-- vì chúng tôi sẽ không để nói về mọi chức năng mà tồn tại trong chuẩn C library-- nhưng tất cả đều có sẵn cho bạn, đặc biệt là nếu bạn có một nhìn vào reference.cs50.net. Và strcmp là một thực sự mạnh mẽ chức năng tồn tại bên trong của tiêu đề string.h tập tin, mà là một tiêu đề tập tin đó là dành riêng cho chức năng mà làm việc và thao tác trên chuỗi. Và đặc biệt, những gì strcmp không là so sánh giá trị của hai chuỗi. Vì vậy, tôi về để Segmentation Fault một cuộc gọi đến strcmp nó có vẻ. Tôi nhấn n, và trong thực tế, tôi nhận được thông báo, Chương trình chấm dứt với tín hiệu SIGSEGV lỗi phân khúc. Vậy bây giờ Tôi thực sự đã seg đứt gãy, và chương trình của tôi có khá nhiều hiệu quả nhất định lên. Đây là phần cuối của chương trình. Nó phá vỡ, nó đã bị rơi. Vì vậy, không phải là rất nhiều, nhưng tôi thực sự đã tìm hiểu khá một chút từ kinh nghiệm này rất ít. Tôi đã học được những gì? Vâng, chương trình của tôi bị treo khá nhiều ngay lập tức. Chương trình của tôi bị treo trên một cuộc gọi để strcmp, nhưng tôi không có bất kỳ biến địa phương trong tôi chương trình tại thời điểm mà nó bị treo. Vì vậy, những gì string, dây, Tôi có thể có thể được so sánh. Nếu tôi không có bất kỳ địa phương biến, có lẽ bạn Tôi phỏng đoán rằng có lẽ have-- là một biến toàn cầu, trong đó có thể đúng. Nhưng nói chung, có vẻ như như tôi đang so sánh để cái gì đó không tồn tại. Vì vậy, đi điều tra mà xa hơn một chút. Vì vậy, tôi sẽ để xóa màn hình của tôi. Tôi sẽ bỏ ra khỏi Môi trường GDB trong một giây. Và tôi nghĩ, OK, vì vậy có không có biến cục bộ trong chương trình của tôi. Tôi tự hỏi nếu có lẽ tôi phải vượt qua trong một chuỗi như là một đối số dòng lệnh. Vì vậy, chúng ta hãy chỉ kiểm tra này ra. Tôi đã không làm điều này trước. Hãy xem nếu có thể nếu tôi chạy chương trình này với một đối số dòng lệnh nó hoạt động. Huh, không có lỗi trong phân khúc đó. Nó chỉ nói với tôi rằng tôi đã tìm nó ra. Vì vậy, có lẽ đó là sửa chữa ở đây. Và quả thực, nếu tôi quay lại và nhìn vào mã nguồn thực tế cho buggy1.c, nó có vẻ như là mặc dù những gì tôi đang làm là Tôi đang thực hiện một cuộc gọi đến mà không strcmp kiểm tra cho dù trên thực tế argv [1] tồn tại. Đây thực sự là mã nguồn cho buggy1.c. Vì vậy, những gì tôi thực sự cần phải làm ở đây để sửa chữa chương trình của tôi, giả sử tôi có nộp trước mặt tôi, là chỉ cần thêm một kiểm tra để đảm chắc chắn rằng argc là bằng 2. Vì vậy, ví dụ này, một lần nữa, như tôi đã nói, là một chút giả tạo, phải không? Bạn thường sẽ không vô tình xóa mã nguồn của bạn và sau đó phải cố gắng và gỡ lỗi chương trình. Nhưng hy vọng rằng, nó đã cho bạn một minh họa của các loại của những điều mà bạn có thể suy nghĩ về như bạn gỡ lỗi chương trình của bạn. Trạng thái của vấn đề ở đây là gì? Những gì tôi làm biến có thể truy cập với tôi? Trường hợp chính xác là chương trình của tôi đâm, vào những gì dòng, về những gì gọi với những gì chức năng? Những loại manh mối nào đó cho tôi? Và đó là chính xác loại tư duy mà bạn nên được nhận vào khi bạn suy nghĩ về gỡ lỗi chương trình của bạn. Tôi Doug Lloyd. Đây là CS50.