1 00:00:00,000 --> 00:00:02,000 [Powered by Google Translate] [Valgrind 2 00:00:02,000 --> 00:00:05,000 [Nate hardison, Đại học Harvard] 3 00:00:05,000 --> 00:00:07,000 Đây là CS50, CS50.TV] 4 00:00:07,000 --> 00:00:10,000 Một số các lỗi khó khăn nhất trong các chương trình C 5 00:00:10,000 --> 00:00:13,000 đến từ sự quản lý yếu kém của bộ nhớ. 6 00:00:13,000 --> 00:00:15,000 Có một số lượng lớn các cách để vít những thứ lên, 7 00:00:15,000 --> 00:00:17,000 bao gồm cả việc phân bổ số tiền sai của bộ nhớ, 8 00:00:17,000 --> 00:00:20,000 quên để khởi tạo các biến, 9 00:00:20,000 --> 00:00:23,000 văn bản trước hoặc sau khi kết thúc của một bộ đệm, 10 00:00:23,000 --> 00:00:25,000 và giải phóng giữ nhiều lần bộ nhớ. 11 00:00:25,000 --> 00:00:28,000 Các triệu chứng bao gồm từ tai nạn liên tục 12 00:00:28,000 --> 00:00:30,000 giá trị bí ẩn ghi đè, 13 00:00:30,000 --> 00:00:34,000 thường tại các địa điểm và thời gian xa khỏi các lỗi ban đầu. 14 00:00:34,000 --> 00:00:37,000 Truy tìm các vấn đề quan sát trở lại nguyên nhân gốc rễ cơ bản 15 00:00:37,000 --> 00:00:39,000 thể được thử thách, 16 00:00:39,000 --> 00:00:42,000 nhưng may mắn thay có một chương trình hữu ích được gọi là Valgrind 17 00:00:42,000 --> 00:00:44,000 có thể làm rất nhiều để giúp đỡ. 18 00:00:44,000 --> 00:00:47,000 >> Bạn chạy một chương trình theo Valgrind để cho phép 19 00:00:47,000 --> 00:00:50,000 mở rộng kiểm tra cấp phát bộ nhớ heap và truy cập. 20 00:00:50,000 --> 00:00:53,000 Khi Valgrind phát hiện một vấn đề, nó sẽ cho bạn ngay lập tức, 21 00:00:53,000 --> 00:00:56,000 thông tin trực tiếp cho phép bạn 22 00:00:56,000 --> 00:00:58,000 dễ dàng tìm thấy và sửa chữa vấn đề. 23 00:00:58,000 --> 00:01:01,000 Valgrind báo cáo về các vấn đề bộ nhớ ít nguy hiểm, 24 00:01:01,000 --> 00:01:04,000 chẳng hạn như rò rỉ bộ nhớ, cấp phát bộ nhớ heap, 25 00:01:04,000 --> 00:01:07,000 và quên để giải phóng nó. 26 00:01:07,000 --> 00:01:10,000 Như Clang trình biên dịch, của chúng tôi, trong trình gỡ lỗi của chúng tôi, GDB, 27 00:01:10,000 --> 00:01:14,000 Valgrind là phần mềm miễn phí, và nó được cài đặt trên thiết bị. 28 00:01:14,000 --> 00:01:16,000 Valgrind chạy vào thực thi nhị phân của bạn, 29 00:01:16,000 --> 00:01:20,000 c của bạn hoặc mã h. các tập tin nguồn, 30 00:01:20,000 --> 00:01:23,000 vì vậy hãy chắc chắn rằng bạn đã biên soạn một bản sao up-to-ngày của chương trình của bạn 31 00:01:23,000 --> 00:01:25,000 sử dụng Clang hoặc Kiếm. 32 00:01:25,000 --> 00:01:28,000 Sau đó, chạy chương trình của bạn dưới Valgrind có thể 33 00:01:28,000 --> 00:01:32,000 đơn giản như chỉ cần đặt trước lệnh chương trình tiêu chuẩn với Valgrind từ, 34 00:01:32,000 --> 00:01:35,000 mà khởi Valgrind và chạy các chương trình bên trong của nó. 35 00:01:35,000 --> 00:01:38,000 Khi bắt đầu, Valgrind hiện một số phức tạp 36 00:01:38,000 --> 00:01:41,000 jiggering để cấu hình thực thi cho các kiểm tra bộ nhớ, 37 00:01:41,000 --> 00:01:44,000 vì vậy nó có thể mất một chút để có được và chạy. 38 00:01:44,000 --> 00:01:48,000 Chương trình sau đó sẽ thực hiện bình thường, có thể là chậm hơn rất nhiều, 39 00:01:48,000 --> 00:01:52,000 và khi nó kết thúc, Valgrind sẽ in một bản tóm tắt của việc sử dụng bộ nhớ của nó. 40 00:01:52,000 --> 00:01:58,000 Nếu mọi việc suôn sẻ, nó sẽ giống như thế này: 41 00:01:58,000 --> 00:02:01,000 Trong trường hợp này, / clean_program. 42 00:02:01,000 --> 00:02:04,000 là đường dẫn đến chương trình tôi muốn chạy. 43 00:02:04,000 --> 00:02:06,000 Và trong khi điều này không có bất kỳ đối số, 44 00:02:06,000 --> 00:02:09,000 nếu nó đã làm tôi muốn chỉ tack đến cuối của lệnh như bình thường. 45 00:02:09,000 --> 00:02:12,000 Sạch chương trình chỉ là một chương trình nhỏ ngớ ngẩn tôi đã tạo 46 00:02:12,000 --> 00:02:15,000 phân bổ không gian cho một khối ints trên heap, 47 00:02:15,000 --> 00:02:19,000 đặt một số giá trị bên trong của họ, và giải phóng toàn bộ khối. 48 00:02:19,000 --> 00:02:23,000 Đây là những gì bạn đang chụp, không có lỗi và không có rò rỉ. 49 00:02:23,000 --> 00:02:27,000 >> Một số liệu khác quan trọng là tổng số byte được phân bổ. 50 00:02:27,000 --> 00:02:32,000 Tùy thuộc vào chương trình, nếu phân bổ của bạn là trong MB hoặc cao hơn, 51 00:02:32,000 --> 00:02:34,000 có lẽ bạn đang làm sai điều gì. 52 00:02:34,000 --> 00:02:37,000 Bạn không cần thiết lưu trữ bản sao? 53 00:02:37,000 --> 00:02:40,000 Bạn đang sử dụng các đống cho việc lưu trữ, khi nào nó sẽ được tốt hơn để sử dụng ngăn xếp? 54 00:02:40,000 --> 00:02:43,000 Vì vậy, lỗi bộ nhớ có thể thực sự ác. 55 00:02:43,000 --> 00:02:46,000 Những người công khai hơn gây ra tai nạn ngoạn mục, 56 00:02:46,000 --> 00:02:49,000 nhưng thậm chí sau đó nó vẫn có thể rất khó xác định 57 00:02:49,000 --> 00:02:51,000 chính xác những gì đã dẫn đến vụ tai nạn. 58 00:02:51,000 --> 00:02:54,000 Ngấm ngầm, một chương trình với một lỗi bộ nhớ 59 00:02:54,000 --> 00:02:56,000 vẫn có thể biên dịch sạch 60 00:02:56,000 --> 00:02:58,000 và dường như vẫn có thể làm việc một cách chính xác 61 00:02:58,000 --> 00:03:01,000 bởi vì bạn quản lý để có được may mắn nhất của thời gian. 62 00:03:01,000 --> 00:03:04,000 Sau khi một số "kết quả thành công, 63 00:03:04,000 --> 00:03:07,000 bạn chỉ có thể nghĩ rằng một vụ tai nạn là sự may mắn của máy tính, 64 00:03:07,000 --> 00:03:10,000 nhưng máy tính không bao giờ sai. 65 00:03:10,000 --> 00:03:13,000 >> Chạy Valgrind có thể giúp bạn tìm ra nguyên nhân gây ra lỗi bộ nhớ có thể nhìn thấy 66 00:03:13,000 --> 00:03:18,000 cũng như tìm ẩn lỗi bạn thậm chí không biết về. 67 00:03:18,000 --> 00:03:22,000 Mỗi lần Valgrind phát hiện một vấn đề, nó in thông tin về những gì quan sát được nó. 68 00:03:22,000 --> 00:03:24,000 Mỗi sản phẩm là khá ngắn gọn - 69 00:03:24,000 --> 00:03:27,000 đường nguồn của lệnh vi phạm, những gì vấn đề là, 70 00:03:27,000 --> 00:03:30,000 và một ít thông tin về bộ nhớ liên quan - 71 00:03:30,000 --> 00:03:34,000 nhưng thường nó đủ thông tin để hướng sự chú ý của bạn đến đúng nơi. 72 00:03:34,000 --> 00:03:37,000 Dưới đây là một ví dụ của Valgrind chạy trên một chương trình lỗi 73 00:03:37,000 --> 00:03:40,000 mà không một chi không hợp lệ của bộ nhớ heap. 74 00:03:40,000 --> 00:03:49,000 Chúng tôi thấy không có lỗi hoặc cảnh báo trong biên soạn. 75 00:03:49,000 --> 00:03:53,000 Uh-oh, bản tóm tắt báo lỗi nói rằng có hai lỗi 76 00:03:53,000 --> 00:03:56,000 hai không hợp lệ đọc của kích thước 4 - byte, đó là. 77 00:03:56,000 --> 00:04:01,000 Xấu cả hai lần đọc xảy ra trong các chức năng chính của invalid_read.c, 78 00:04:01,000 --> 00:04:04,000 người đầu tiên trên dòng 16 và thứ hai trên dòng 19. 79 00:04:04,000 --> 00:04:06,000 Chúng ta hãy nhìn vào mã. 80 00:04:06,000 --> 00:04:11,000 Hình như cuộc gọi đầu tiên printf cố gắng để đọc một int quá khứ kết thúc của khối bộ nhớ của chúng tôi. 81 00:04:11,000 --> 00:04:13,000 Nếu chúng ta nhìn lại tại đầu ra của Valgrind, 82 00:04:13,000 --> 00:04:16,000 chúng ta thấy rằng Valgrind nói với chúng tôi chính xác điều đó. 83 00:04:16,000 --> 00:04:19,000 Địa chỉ chúng tôi đang cố gắng để đọc bắt đầu 0 byte 84 00:04:19,000 --> 00:04:22,000 quá khứ kết thúc của khối có kích thước 16 byte - 85 00:04:22,000 --> 00:04:25,000 bốn 32-bit ints mà chúng tôi phân bổ. 86 00:04:25,000 --> 00:04:29,000 Đó là, các địa chỉ chúng tôi đã cố gắng để đọc bắt đầu vào cuối của khối của chúng tôi, 87 00:04:29,000 --> 00:04:32,000 cũng giống như chúng ta thấy trong cuộc gọi printf xấu của chúng tôi. 88 00:04:32,000 --> 00:04:36,000 Bây giờ, không hợp lệ lần đọc có thể không có vẻ như là lớn của một thỏa thuận, 89 00:04:36,000 --> 00:04:39,000 nhưng nếu bạn đang sử dụng dữ liệu đó để kiểm soát dòng chảy của chương trình của bạn - 90 00:04:39,000 --> 00:04:42,000 ví dụ, như một phần của tuyên bố nếu hay vòng lặp - 91 00:04:42,000 --> 00:04:45,000 sau đó mọi thứ có thể âm thầm xấu đi. 92 00:04:45,000 --> 00:04:47,000 Xem làm thế nào tôi có thể chạy chương trình invalid_read 93 00:04:47,000 --> 00:04:50,000 và không có gì khác thường xảy ra. 94 00:04:50,000 --> 00:04:52,000 Scary, huh? 95 00:04:52,000 --> 00:04:56,000 >> Bây giờ, hãy nhìn vào các loại một số chi tiết của các lỗi mà bạn có thể gặp phải trong mã của bạn, 96 00:04:56,000 --> 00:04:59,000 và chúng tôi sẽ xem Valgrind phát hiện chúng. 97 00:04:59,000 --> 00:05:01,000 Chúng tôi chỉ thấy một ví dụ về một invalid_read, 98 00:05:01,000 --> 00:05:04,000 vì vậy bây giờ chúng ta hãy kiểm tra một invalid_write. 99 00:05:04,000 --> 00:05:09,000 Một lần nữa, không có lỗi hoặc cảnh báo trong biên soạn. 100 00:05:09,000 --> 00:05:12,000 Được rồi, Valgrind nói rằng có hai lỗi trong chương trình này - 101 00:05:12,000 --> 00:05:15,000 và invalid_write và invalid_read một. 102 00:05:15,000 --> 00:05:18,000 Hãy kiểm tra mã này. 103 00:05:18,000 --> 00:05:21,000 Hình như chúng ta đã có một ví dụ cổ điển strlen cộng 1 lỗi. 104 00:05:21,000 --> 00:05:24,000 Mã không malloc thêm một byte của không gian 105 00:05:24,000 --> 00:05:26,000 cho các nhân vật / 0, 106 00:05:26,000 --> 00:05:30,000 vì vậy khi str bản sao đi để viết nó ở ssubstrlen "CS50 đá!" 107 00:05:30,000 --> 00:05:33,000 nó đã viết 1 byte quá khứ kết thúc của khối của chúng tôi. 108 00:05:33,000 --> 00:05:36,000 Invalid_read đến khi chúng tôi thực hiện cuộc gọi của chúng tôi để printf. 109 00:05:36,000 --> 00:05:40,000 Printf kết thúc đọc bộ nhớ không hợp lệ khi nó đọc / 0 ký tự 110 00:05:40,000 --> 00:05:43,000 vì nó trông vào cuối của chuỗi này E nó in ấn. 111 00:05:43,000 --> 00:05:45,000 Tuy nhiên, không ai trong số này trốn thoát Valgrind. 112 00:05:45,000 --> 00:05:48,000 Chúng ta thấy rằng nó bắt invalid_write như một phần của bản sao str 113 00:05:48,000 --> 00:05:51,000 trên dòng 11 của chính invalid_read là một phần của printf. 114 00:05:51,000 --> 00:05:54,000 Đá, Valgrind. 115 00:05:54,000 --> 00:05:57,000 Một lần nữa, điều này có thể không có vẻ như là một việc lớn. 116 00:05:57,000 --> 00:06:00,000 Chúng ta có thể chạy chương trình này hơn và hơn bên ngoài Valgrind 117 00:06:00,000 --> 00:06:03,000 và không thấy bất kỳ triệu chứng lỗi. 118 00:06:03,000 --> 00:06:06,000 >> Tuy nhiên, chúng ta hãy nhìn vào một biến thể nhẹ này để xem 119 00:06:06,000 --> 00:06:09,000 làm thế nào những điều có thể nhận được thực sự xấu. 120 00:06:09,000 --> 00:06:14,000 Vì vậy, các cấp, chúng ta đang lạm dụng nhiều điều hơn một chút trong mã này. 121 00:06:14,000 --> 00:06:17,000 Chúng tôi chỉ phân bổ không gian trên heap cho hai chuỗi 122 00:06:17,000 --> 00:06:19,000 chiều dài của CS50 đá, 123 00:06:19,000 --> 00:06:22,000 thời gian này, nhớ / 0 ký tự. 124 00:06:22,000 --> 00:06:25,000 Nhưng sau đó chúng tôi ném trong một chuỗi siêu dài vào khối nhớ 125 00:06:25,000 --> 00:06:27,000 rằng S được trỏ đến. 126 00:06:27,000 --> 00:06:30,000 Sẽ có ảnh hưởng trên các khối nhớ rằng T điểm? 127 00:06:30,000 --> 00:06:34,000 Vâng, nếu T điểm tới bộ nhớ mà chỉ tiếp giáp với S, 128 00:06:34,000 --> 00:06:37,000 ngay sau khi, 129 00:06:37,000 --> 00:06:39,000 sau đó chúng ta có thể viết trên một phần của T. 130 00:06:39,000 --> 00:06:41,000 Hãy chạy mã này. 131 00:06:41,000 --> 00:06:43,000 Hãy nhìn vào những gì đã xảy ra. 132 00:06:43,000 --> 00:06:47,000 Các chuỗi chúng tôi lưu trữ trong các khối đống của chúng tôi cả hai dường như đã in ra một cách chính xác. 133 00:06:47,000 --> 00:06:49,000 Dường như không có gì sai cả. 134 00:06:49,000 --> 00:06:52,000 Tuy nhiên, chúng ta hãy quay trở lại mã của chúng tôi và 135 00:06:52,000 --> 00:06:55,000 nhận xét ra đường, nơi chúng tôi sao chép CS50 đá 136 00:06:55,000 --> 00:06:59,000 vào khối bộ nhớ thứ hai, chỉ bởi t. 137 00:06:59,000 --> 00:07:02,000 Bây giờ, khi chúng tôi chạy mã này, chúng ta nên 138 00:07:02,000 --> 00:07:06,000 chỉ nhìn thấy các nội dung của khối bộ nhớ đầu tiên in ra. 139 00:07:06,000 --> 00:07:09,000 Whoa, mặc dù chúng tôi đã không str bản sao 140 00:07:09,000 --> 00:07:12,000 bất kỳ ký tự vào khối đống thứ hai, là chỉ bởi T, 141 00:07:12,000 --> 00:07:15,000 chúng tôi nhận được một in ra. 142 00:07:15,000 --> 00:07:18,000 Thật vậy, các chuỗi, chúng tôi nhồi vào khối đầu tiên của chúng tôi 143 00:07:18,000 --> 00:07:21,000 tràn ngập khối đầu tiên và vào khối thứ hai, 144 00:07:21,000 --> 00:07:23,000 làm cho tất cả mọi thứ có vẻ bình thường. 145 00:07:23,000 --> 00:07:26,000 Valgrind, mặc dù, cho chúng ta biết câu chuyện có thật. 146 00:07:26,000 --> 00:07:28,000 Hiện chúng tôi đi. 147 00:07:28,000 --> 00:07:32,000 Tất cả những người không hợp lệ đọc và viết. 148 00:07:32,000 --> 00:07:36,000 >> Hãy nhìn vào một ví dụ về một loại lỗi khác. 149 00:07:36,000 --> 00:07:39,000 Ở đây chúng tôi làm điều gì đó chứ không phải bất hạnh. 150 00:07:39,000 --> 00:07:41,000 Chúng tôi lấy không gian cho một int trên heap, 151 00:07:41,000 --> 00:07:45,000 và chúng ta khởi tạo một con trỏ int - p - để trỏ đến không gian đó. 152 00:07:45,000 --> 00:07:48,000 Tuy nhiên, trong khi con trỏ của chúng tôi được khởi tạo, 153 00:07:48,000 --> 00:07:52,000 các dữ liệu mà nó trỏ đến bất cứ điều gì rác trong một phần của heap. 154 00:07:52,000 --> 00:07:55,000 Vì vậy, khi chúng ta nạp dữ liệu đó vào int i, 155 00:07:55,000 --> 00:07:57,000 chúng tôi kỹ thuật khởi tạo i, 156 00:07:57,000 --> 00:08:00,000 nhưng chúng tôi làm như vậy với các dữ liệu rác. 157 00:08:00,000 --> 00:08:03,000 Các cuộc gọi đến khẳng định, mà là một tiện dụng gỡ lỗi vĩ mô 158 00:08:03,000 --> 00:08:06,000 được định nghĩa trong thư viện khẳng định aptly tên, 159 00:08:06,000 --> 00:08:09,000 sẽ hủy bỏ chương trình nếu điều kiện thử nghiệm của nó không thành công. 160 00:08:09,000 --> 00:08:11,000 Nghĩa là, nếu tôi không phải là 0. 161 00:08:11,000 --> 00:08:14,000 Tùy thuộc vào những gì đã được trong không gian đống, chỉ bằng p, 162 00:08:14,000 --> 00:08:18,000 chương trình này có thể làm việc và đôi khi thất bại tại các thời điểm khác. 163 00:08:18,000 --> 00:08:20,000 Nếu nó hoạt động, chúng tôi chỉ nhận được may mắn. 164 00:08:20,000 --> 00:08:24,000 Trình biên dịch sẽ không bắt lỗi này, nhưng Valgrind sẽ chắc chắn. 165 00:08:24,000 --> 00:08:28,000 Hiện chúng tôi thấy thông báo lỗi xuất phát từ việc sử dụng của chúng tôi rằng các dữ liệu rác. 166 00:08:28,000 --> 00:08:32,000 >> Khi bạn phân bổ bộ nhớ heap nhưng không deallocate nó hoặc giải phóng nó, 167 00:08:32,000 --> 00:08:34,000 đó được gọi là bị rò rỉ. 168 00:08:34,000 --> 00:08:37,000 Đối với một chương trình nhỏ, ngắn ngủi, chạy và ngay lập tức thoát ra, 169 00:08:37,000 --> 00:08:39,000 rò rỉ là vô hại, 170 00:08:39,000 --> 00:08:42,000 nhưng đối với một dự án của kích thước lớn hơn và / hoặc kéo dài tuổi thọ, 171 00:08:42,000 --> 00:08:46,000 thậm chí là một rò rỉ nhỏ có thể hợp chất thành một cái gì đó lớn. 172 00:08:46,000 --> 00:08:49,000 Đối với CS50, chúng tôi mong đợi bạn 173 00:08:49,000 --> 00:08:51,000 chăm sóc giải phóng tất cả các bộ nhớ heap mà bạn phân bổ, 174 00:08:51,000 --> 00:08:54,000 vì chúng tôi muốn bạn để xây dựng các kỹ năng để xử lý đúng quy trình hướng dẫn sử dụng 175 00:08:54,000 --> 00:08:56,000 yêu cầu của C. 176 00:08:56,000 --> 00:08:59,000 Để làm như vậy, chương trình của bạn cần phải có một chính xác 177 00:08:59,000 --> 00:09:03,000 một-một sự tương ứng giữa malloc và các cuộc gọi miễn phí. 178 00:09:03,000 --> 00:09:06,000 May mắn thay, Valgrind có thể giúp bạn với rò rỉ bộ nhớ. 179 00:09:06,000 --> 00:09:09,000 Đây là một chương trình bị rò rỉ được gọi là leak.c giao 180 00:09:09,000 --> 00:09:13,000 không gian trên heap, viết cho nó, nhưng không giải phóng nó. 181 00:09:13,000 --> 00:09:16,000 Chúng tôi biên dịch nó với Thực hiện và chạy nó dưới Valgrind, 182 00:09:16,000 --> 00:09:18,000 và chúng ta thấy rằng, trong khi chúng ta không có lỗi bộ nhớ, 183 00:09:18,000 --> 00:09:20,000 chúng tôi có một bị rò rỉ. 184 00:09:20,000 --> 00:09:23,000 Có 16 byte chắc chắn bị mất, 185 00:09:23,000 --> 00:09:27,000 điều đó có nghĩa là con trỏ tới bộ nhớ mà không phải là trong phạm vi khi chương trình đã thoát. 186 00:09:27,000 --> 00:09:30,000 Bây giờ, Valgrind không cung cấp cho chúng tôi một tấn thông tin về rò rỉ, 187 00:09:30,000 --> 00:09:35,000 nhưng nếu chúng ta tuân theo lưu ý nhỏ này mà nó mang lại cho xuống phía dưới cùng của báo cáo của mình 188 00:09:35,000 --> 00:09:38,000 chạy lại với rò rỉ kiểm tra = đầy đủ 189 00:09:38,000 --> 00:09:41,000 để xem chi tiết đầy đủ của bộ nhớ bị rò rỉ, 190 00:09:41,000 --> 00:09:44,000 chúng tôi sẽ nhận được thêm thông tin. 191 00:09:44,000 --> 00:09:46,000 Bây giờ, trong phần tóm tắt đống, 192 00:09:46,000 --> 00:09:50,000 Valgrind cho chúng ta biết nơi mà bộ nhớ bị mất đã được cấp ban đầu. 193 00:09:50,000 --> 00:09:52,000 Cũng như chúng ta biết từ trong mã nguồn, 194 00:09:52,000 --> 00:09:55,000 Valgrind thông báo với chúng tôi rằng chúng tôi bị rò rỉ bộ nhớ 195 00:09:55,000 --> 00:09:58,000 được phân bổ với một cuộc gọi đến malloc vào dòng 8 của leak.c 196 00:09:58,000 --> 00:10:00,000 trong các chức năng chính. 197 00:10:00,000 --> 00:10:02,000 Khá tiện lợi. 198 00:10:02,000 --> 00:10:04,000 >> Valgrind phân loại rò rỉ bằng cách sử dụng các thuật ngữ này: 199 00:10:04,000 --> 00:10:07,000 Chắc chắn bị mất - đây là cấp phát bộ nhớ heap 200 00:10:07,000 --> 00:10:10,000 mà chương trình không còn có một con trỏ. 201 00:10:10,000 --> 00:10:14,000 Valgrind biết rằng bạn đã có một lần con trỏ, nhưng đã bị mất theo dõi của nó. 202 00:10:14,000 --> 00:10:17,000 Bộ nhớ này chắc chắn là bị rò rỉ. 203 00:10:17,000 --> 00:10:20,000 Gián tiếp bị mất - đây là cấp phát bộ nhớ heap 204 00:10:20,000 --> 00:10:24,000 mà các con trỏ chỉ vào nó cũng bị mất. 205 00:10:24,000 --> 00:10:27,000 Ví dụ, nếu bạn bị mất con trỏ của bạn để nút đầu tiên của một danh sách liên kết, 206 00:10:27,000 --> 00:10:30,000 sau đó là nút đầu tiên chắc chắn sẽ bị mất, 207 00:10:30,000 --> 00:10:34,000 trong khi bất kỳ các nút tiếp theo sẽ được gián tiếp bị mất. 208 00:10:34,000 --> 00:10:37,000 Có thể bị mất - đây là cấp phát bộ nhớ heap 209 00:10:37,000 --> 00:10:41,000 mà Valgrind không thể chắc chắn liệu có là một con trỏ hay không. 210 00:10:41,000 --> 00:10:44,000 Vẫn có thể truy cập là cấp phát bộ nhớ heap 211 00:10:44,000 --> 00:10:47,000 mà chương trình vẫn có một con trỏ ở lối ra, 212 00:10:47,000 --> 00:10:50,000 mà thường có nghĩa là một biến toàn cầu trỏ đến nó. 213 00:10:50,000 --> 00:10:53,000 Để kiểm tra cho các rò rỉ, bạn cũng sẽ phải bao gồm các tùy chọn 214 00:10:53,000 --> 00:10:55,000 - Vẫn có thể truy cập = có 215 00:10:55,000 --> 00:10:58,000 trong invocation của bạn Valgrind. 216 00:10:58,000 --> 00:11:01,000 >> Những trường hợp khác nhau có thể yêu cầu các chiến lược khác nhau để làm sạch chúng, 217 00:11:01,000 --> 00:11:05,000 nhưng rò rỉ nên loại bỏ. 218 00:11:05,000 --> 00:11:08,000 Thật không may, sửa chữa rò rỉ có thể là khó khăn để làm, 219 00:11:08,000 --> 00:11:11,000 kể từ khi các cuộc gọi không chính xác để miễn phí có thể thổi lên chương trình của bạn. 220 00:11:11,000 --> 00:11:14,000 Ví dụ, nếu chúng ta nhìn vào invalid_free.c, 221 00:11:14,000 --> 00:11:18,000 chúng ta thấy một ví dụ về deallocation trí nhớ kém. 222 00:11:18,000 --> 00:11:21,000 Những gì nên được một cuộc gọi duy nhất để giải phóng toàn bộ khối 223 00:11:21,000 --> 00:11:24,000 bộ nhớ chỉ bởi int_block, 224 00:11:24,000 --> 00:11:27,000 thay vì trở thành một nỗ lực để giải phóng từng phần int có kích thước 225 00:11:27,000 --> 00:11:29,000 bộ nhớ riêng. 226 00:11:29,000 --> 00:11:32,000 Điều này sẽ không hư hại. 227 00:11:32,000 --> 00:11:34,000 Boom! Thật là một lỗi. 228 00:11:34,000 --> 00:11:36,000 Điều này chắc chắn là không tốt. 229 00:11:36,000 --> 00:11:39,000 Nếu bạn đang mắc kẹt với các loại hình báo lỗi, mặc dù, và bạn không biết nơi để tìm, 230 00:11:39,000 --> 00:11:41,000 rơi trở lại người bạn tốt nhất của bạn mới. 231 00:11:41,000 --> 00:11:44,000 Bạn đoán nó - Valgrind. 232 00:11:44,000 --> 00:11:47,000 Valgrind, như mọi khi, biết chính xác những gì. 233 00:11:47,000 --> 00:11:50,000 Các tính alloc và miễn phí không phù hợp. 234 00:11:50,000 --> 00:11:52,000 Chúng tôi đã có 1 alloc và 4 giải phóng. 235 00:11:52,000 --> 00:11:55,000 Và Valgrind cũng cho chúng ta biết nơi mà các cuộc gọi miễn phí đầu tiên xấu - 236 00:11:55,000 --> 00:11:58,000 đã kích hoạt blowup là đến từ - 237 00:11:58,000 --> 00:12:00,000 dòng 16. 238 00:12:00,000 --> 00:12:03,000 Như bạn thấy, các cuộc gọi xấu để giải phóng thực sự tồi tệ, 239 00:12:03,000 --> 00:12:05,000 vì vậy chúng tôi khuyên bạn nên để cho chương trình của bạn bị rò rỉ 240 00:12:05,000 --> 00:12:08,000 trong khi bạn đang làm việc trên nhận được các chức năng chính xác. 241 00:12:08,000 --> 00:12:12,000 Bắt đầu tìm kiếm các chỗ rò rỉ chỉ sau khi chương trình của bạn đang làm việc đúng, 242 00:12:12,000 --> 00:12:14,000 mà không có bất kỳ lỗi nào khác. 243 00:12:14,000 --> 00:12:16,000 >> Và đó là tất cả chúng tôi đã có cho video này. 244 00:12:16,000 --> 00:12:18,000 Bây giờ bạn còn chờ gì nữa? 245 00:12:18,000 --> 00:12:21,000 Đi chạy Valgrind về các chương trình của bạn ngay bây giờ. 246 00:12:21,000 --> 00:12:25,000 Tên là Nate hardison. Đây là CS50. [CS50.TV]