Gỡ lỗi bộ nhớ


23

Trước hết, tôi nhận ra đây không phải là một câu hỏi kiểu hỏi đáp hoàn hảo với một câu trả lời tuyệt đối, nhưng tôi không thể nghĩ ra bất kỳ từ ngữ nào để làm cho nó hoạt động tốt hơn. Tôi không nghĩ có một giải pháp tuyệt đối cho vấn đề này và đây là một trong những lý do tại sao tôi đăng nó ở đây thay vì Stack Overflow.

Trong tháng trước tôi đã viết lại một đoạn mã máy chủ khá cũ (mmorpg) để hiện đại hơn và dễ dàng mở rộng / mod hơn. Tôi bắt đầu với phần mạng và triển khai thư viện bên thứ 3 (miễn cưỡng) để xử lý công cụ cho tôi. Với tất cả các thay đổi mã và bao thanh toán, tôi đã giới thiệu tham nhũng bộ nhớ ở đâu đó và tôi đã phải vật lộn để tìm ra nơi nó xảy ra.

Tôi dường như không thể tái tạo nó một cách đáng tin cậy trên môi trường dev / test của mình, ngay cả khi triển khai các bot nguyên thủy để mô phỏng một số tải tôi không gặp sự cố nữa (Tôi đã khắc phục sự cố không đáng có gây ra một số nội dung)

Tôi đã thử cho đến nay:

Đánh bại địa ngục khỏi nó - Không có ghi không hợp lệ cho đến khi sự cố xảy ra (có thể mất hơn 1 ngày sản xuất .. hoặc chỉ một giờ) thực sự gây trở ngại cho tôi, chắc chắn đến một lúc nào đó, nó sẽ truy cập vào bộ nhớ không hợp lệ và không ghi đè lên công cụ cơ hội? (Có cách nào để "dàn trải" phạm vi địa chỉ không?)

Các công cụ phân tích mã, cụ thể là độ phủ và cppcheck. Trong khi họ đã chỉ ra một số trường hợp khó chịu và cạnh trong mã thì không có gì nghiêm trọng.

Ghi lại quá trình cho đến khi nó gặp sự cố với gdb (thông qua undodb) và sau đó làm việc theo cách của tôi ngược lại. Điều này / âm thanh / giống như nó có thể thực hiện được, nhưng tôi sẽ kết thúc sự cố gdb bằng cách sử dụng tính năng tự động hoàn thành hoặc tôi kết thúc trong một cấu trúc tự nguyện nội bộ nơi tôi bị lạc vì có quá nhiều nhánh có thể xảy ra (một lỗi gây ra lỗi khác và do đó trên). Tôi đoán sẽ thật tuyệt nếu tôi có thể thấy con trỏ ban đầu thuộc về / nơi nó được phân bổ, điều đó sẽ loại bỏ hầu hết các vấn đề phân nhánh. Tôi không thể chạy valgrind với undodb, và tôi bản ghi gdb bình thường chậm một cách bất thường (nếu điều đó thậm chí hoạt động kết hợp với valgrind).

Xem lại mã! Một mình (triệt để) và có một số người bạn xem qua mã của tôi, mặc dù tôi nghi ngờ nó đã đủ kỹ lưỡng. Tôi đã suy nghĩ về việc có thể thuê một nhà phát triển để thực hiện một số đánh giá / gỡ lỗi mã với tôi, nhưng tôi không đủ khả năng để bỏ quá nhiều tiền vào đó và tôi không biết tìm ai đó sẵn sàng làm việc cho ít- không - không có tiền nếu anh ta không tìm thấy vấn đề hoặc bất cứ ai đủ điều kiện.

Tôi cũng nên lưu ý: tôi thường nhận được backtraces nhất quán. Có một vài nơi xảy ra sự cố, chủ yếu liên quan đến lớp socket bị hỏng theo cách nào đó. Có thể là một con trỏ không hợp lệ chỉ vào một cái gì đó không phải là một socket hoặc chính lớp socket bị ghi đè lên (một phần?) Với sự vô nghĩa. Mặc dù tôi nghi ngờ nó bị sập ở đó nhiều nhất vì đó là một trong những bộ phận được sử dụng nhiều nhất, vì vậy đó là bộ nhớ bị hỏng đầu tiên được sử dụng.

Tất cả trong tất cả các vấn đề này đã khiến tôi bận rộn gần 2 tháng (nhiều lần và nhiều hơn, một dự án sở thích) và thực sự làm tôi thất vọng đến mức tôi trở thành IRL gắt gỏng và nghĩ về việc từ bỏ. Tôi chỉ không thể nghĩ về những gì tôi phải làm để tìm ra vấn đề.

Có bất kỳ kỹ thuật hữu ích tôi đã bỏ lỡ? Làm thế nào để bạn đối phó với điều đó? (Không thể phổ biến vì không có nhiều thông tin về điều này .. hoặc tôi thực sự bị mù?)

Chỉnh sửa:

Một số thông số kỹ thuật trong trường hợp nó quan trọng:

Sử dụng c ++ (11) qua gcc 4.7 (phiên bản được cung cấp bởi debian wheezy)

Các codebase là khoảng 150k dòng

Chỉnh sửa để phản hồi bài đăng của david.pfx: (xin lỗi vì phản hồi chậm)

Bạn đang giữ hồ sơ cẩn thận của các sự cố, để tìm kiếm các mẫu?

Vâng, tôi vẫn còn những đống đổ vỡ gần đây

Là một vài nơi thực sự giống nhau? Bằng cách nào?

Chà, trong phiên bản gần đây nhất (chúng dường như thay đổi bất cứ khi nào tôi thêm / xóa mã hoặc thay đổi cấu trúc liên quan), nó sẽ luôn bị bắt trong một phương thức hẹn giờ vật phẩm. Về cơ bản một mặt hàng có một thời gian cụ thể sau đó nó hết hạn và nó sẽ gửi thông tin cập nhật cho khách hàng. Con trỏ socket không hợp lệ sẽ ở trong lớp (vẫn hợp lệ theo như tôi có thể nói) lớp Player, chủ yếu liên quan đến điều đó. Tôi cũng đang trải qua vô số sự cố trong giai đoạn dọn dẹp, sau khi tắt máy bình thường, nơi nó phá hủy tất cả các lớp tĩnh chưa bị phá hủy rõ ràng ( __run_exit_handlerstrong backtrace). Chủ yếu liên quan đến std::mapmột lớp, đoán rằng đó chỉ là điều đầu tiên xuất hiện.

Dữ liệu tham nhũng trông như thế nào? Số không? Thăng thiên? Hoa văn?

Tôi chưa tìm thấy bất kỳ mẫu nào, dường như hơi ngẫu nhiên đối với tôi. Thật khó để nói vì tôi không biết tham nhũng bắt đầu từ đâu.

Có liên quan đến đống?

Nó hoàn toàn liên quan đến đống (Tôi đã kích hoạt bảo vệ ngăn xếp của gcc và điều đó không bắt được gì).

Có tham nhũng xảy ra sau một free()?

Bạn sẽ phải giải thích một chút về điều đó. Bạn có nghĩa là có con trỏ của các đối tượng đã được tự do nằm xung quanh? Tôi đang đặt mọi tham chiếu thành null khi đối tượng bị phá hủy, vì vậy trừ khi tôi bỏ lỡ điều gì đó ở đâu đó, không. Điều đó sẽ xuất hiện trong valgrind mặc dù điều đó đã không xảy ra.

Có điều gì đặc biệt về lưu lượng mạng (kích thước bộ đệm, chu kỳ phục hồi) không?

Lưu lượng mạng bao gồm dữ liệu thô. Vì vậy, các mảng char, (u) intX_t hoặc các cấu trúc đóng gói (để loại bỏ phần đệm) cho những thứ phức tạp hơn, mỗi gói có một tiêu đề bao gồm một id và chính kích thước gói được xác nhận theo kích thước dự kiến. Chúng có dung lượng khoảng 10-60byte với gói lớn nhất (boot bootup 'nội bộ, được bắn một lần khi khởi động) có kích thước vài Mb.

Rất nhiều và rất nhiều khẳng định sản xuất. Sụp đổ sớm và dự đoán trước khi thiệt hại lan truyền.

Tôi đã từng gặp một sự cố liên quan đến std::maptham nhũng, mỗi thực thể có một bản đồ về "chế độ xem", mỗi thực thể có thể nhìn thấy nó và ngược lại là trong đó. Tôi đã thêm một bộ đệm 200byte ở phía trước và sau, điền vào nó bằng 0x33 và kiểm tra nó trước mỗi lần truy cập. Tham nhũng đã biến mất một cách kỳ diệu, tôi phải di chuyển thứ gì đó khiến nó bị hỏng thứ khác.

Ghi nhật ký chiến lược, để bạn biết chính xác những gì đang xảy ra trước đó. Thêm vào đăng nhập khi bạn đến gần hơn với một câu trả lời.

Nó hoạt động .. đến một phần mở rộng.

Trong tuyệt vọng, bạn có thể lưu trạng thái và tự động khởi động lại không? Tôi có thể nghĩ về một vài phần mềm sản xuất làm điều đó.

Tôi phần nào làm điều đó. Phần mềm này bao gồm một quá trình "bộ đệm" chính và một số công nhân khác mà tất cả đều truy cập vào bộ đệm để lấy và lưu nội dung. Vì vậy, mỗi lần đổ vỡ tôi không mất nhiều tiến bộ, nó vẫn ngắt kết nối tất cả người dùng và cứ thế, đó chắc chắn không phải là một giải pháp.

Đồng thời: luồng, điều kiện cuộc đua, vv

Có một luồng mysql để thực hiện các truy vấn "không đồng bộ", tất cả đều chưa được xử lý và chỉ chia sẻ thông tin cho lớp cơ sở dữ liệu thông qua các hàm với tất cả các khóa.

Ngắt

Có một bộ đếm thời gian ngắt để ngăn nó khóa mà chỉ hủy bỏ nếu nó không hoàn thành một chu kỳ trong 30 giây, mã đó vẫn an toàn:

if (!tics) {
    abort();
} else
    tics = 0;

Tics được volatile int tics = 0;tăng lên mỗi khi một chu kỳ được hoàn thành. Mã cũ cũng vậy.

sự kiện / cuộc gọi lại / trường hợp ngoại lệ: trạng thái hỏng hoặc ngăn xếp không thể đoán trước

Rất nhiều cuộc gọi lại đang được sử dụng (I / O mạng không đồng bộ, bộ hẹn giờ), nhưng chúng không nên làm gì xấu.

Dữ liệu bất thường: dữ liệu đầu vào bất thường / thời gian / trạng thái

Tôi đã có một vài trường hợp cạnh liên quan đến điều đó. Ngắt kết nối ổ cắm trong khi các gói vẫn đang được xử lý dẫn đến việc truy cập nullptr và như vậy, nhưng chúng dễ dàng được phát hiện cho đến nay vì mọi tham chiếu đều được dọn sạch ngay sau khi nói với lớp đó. (Bản thân sự hủy diệt được xử lý bằng một vòng lặp xóa tất cả các đối tượng bị phá hủy trong mỗi chu kỳ)

Sự phụ thuộc vào một quá trình bên ngoài không đồng bộ.

Quan tâm đến công phu? Đây là một số trường hợp, quá trình bộ nhớ cache được đề cập ở trên. Điều duy nhất tôi có thể tưởng tượng ra khỏi đỉnh đầu là nó sẽ không hoàn thành đủ nhanh và sử dụng dữ liệu rác, nhưng đó không phải là trường hợp vì điều đó cũng sử dụng mạng. Mô hình gói giống nhau.


7
Đáng buồn thay, điều này là phổ biến trong các ứng dụng C ++ không tầm thường. Nếu bạn đang sử dụng kiểm soát nguồn, kiểm tra các thay đổi khác nhau để thu hẹp thay đổi mã nào gây ra sự cố có thể giúp ích, nhưng có thể không khả thi trong trường hợp này.
Telastyn

Vâng, nó thực sự không khả thi trong trường hợp của tôi. Về cơ bản, tôi đã đi từ làm việc đến hoàn toàn và hoàn toàn bị phá vỡ trong 2 tháng và sau đó đến giai đoạn gỡ lỗi nơi tôi có một số mã làm việc. Hệ thống cũ thực sự không cho phép tôi triển khai mã mạng linh hoạt mới mà không phá vỡ mọi thứ.
Robin

2
Tại thời điểm này, bạn có thể phải cố gắng và cô lập từng phần. Lấy từng lớp / tập hợp con của giải pháp, tạo một bản giả xung quanh nó để nó có thể hoạt động và kiểm tra địa ngục sống ra khỏi nó cho đến khi bạn tìm thấy phần thất bại.
Ampt

bắt đầu bằng cách bình luận các phần mã cho đến khi bạn không gặp sự cố nữa.
cpp81

1
Ngoài Valgrind, Coverity và cppcheck, bạn nên thêm Asan và UBsan vào chế độ thử nghiệm của mình. Nếu mã của bạn là corss-platofrm, thì hãy thêm Bộ phân tích doanh nghiệp của Microsoft ( /analyze) và bộ bảo vệ Malloc và Scribble của Apple. Bạn cũng nên sử dụng càng nhiều trình biên dịch càng tốt bằng cách sử dụng càng nhiều tiêu chuẩn càng tốt bởi vì các cảnh báo của trình biên dịch là một chẩn đoán và chúng sẽ tốt hơn theo thời gian. Không có viên đạn bạc, và một kích thước không phù hợp với tất cả. Càng sử dụng nhiều công cụ và trình biên dịch, phạm vi bảo hiểm càng đầy đủ vì mỗi công cụ đều có điểm mạnh và điểm yếu.

Câu trả lời:


21

Đó là một vấn đề đầy thách thức nhưng tôi nghi ngờ có rất nhiều manh mối được tìm thấy trong các vụ tai nạn mà bạn đã thấy.

  • Bạn đang giữ hồ sơ cẩn thận của các sự cố, để tìm kiếm các mẫu?
  • Là một vài nơi thực sự giống nhau? Bằng cách nào?
  • Dữ liệu tham nhũng trông như thế nào? Số không? Thăng thiên? Hoa văn?
  • Có bất kỳ đa luồng liên quan? Nó có thể là một điều kiện cuộc đua?
  • Có liên quan đến đống? Có tham nhũng xảy ra sau khi một () miễn phí?
  • Có liên quan đến ngăn xếp? Liệu ngăn xếp có bị hỏng?
  • Là một tài liệu tham khảo lơ lửng một khả năng? Một giá trị dữ liệu thay đổi một cách bí ẩn?
  • Có điều gì đặc biệt về lưu lượng mạng (kích thước bộ đệm, chu kỳ phục hồi) không?

Những thứ chúng ta đã sử dụng trong các tình huống tương tự.

  • Rất nhiều và rất nhiều khẳng định sản xuất. Sụp đổ sớm và dự đoán trước khi thiệt hại lan truyền.
  • Rất nhiều và rất nhiều vệ sĩ. Các mục dữ liệu bổ sung trước và sau các biến cục bộ, các đối tượng và mallocs () được đặt thành một giá trị và sau đó được kiểm tra thường xuyên.
  • Ghi nhật ký chiến lược, để bạn biết chính xác những gì đang xảy ra trước đó. Thêm vào đăng nhập khi bạn đến gần hơn với một câu trả lời.

Trong tuyệt vọng, bạn có thể lưu trạng thái và tự động khởi động lại không? Tôi có thể nghĩ về một vài phần mềm sản xuất làm điều đó.

Hãy thêm chi tiết nếu chúng tôi có thể giúp đỡ.


Tôi có thể chỉ thêm rằng những lỗi không xác định nghiêm trọng như thế này không phải là tất cả những gì phổ biến và không có nhiều thứ có thể (thường) gây ra chúng. Chúng bao gồm:

  • Đồng thời: luồng, điều kiện cuộc đua, vv
  • Ngắt / sự kiện / gọi lại / ngoại lệ: trạng thái hỏng hoặc ngăn xếp không thể đoán trước
  • Dữ liệu bất thường: dữ liệu đầu vào không đúng lúc / thời gian / trạng thái
  • Sự phụ thuộc vào một quá trình bên ngoài không đồng bộ.

Đây là những phần của mã để tập trung vào.


+1 Tất cả các đề xuất tốt, đặc biệt là các xác nhận, bảo vệ và đăng nhập.
andy256

Tôi đã chỉnh sửa một số thông tin trong câu hỏi của tôi như là một câu trả lời cho câu trả lời của bạn. Điều đó thực sự khiến tôi nghĩ về các sự cố khi tắt mà tôi chưa nhìn rộng rãi, vì vậy tôi sẽ tiếp tục điều đó ngay bây giờ tôi đoán.
Robin

5

Sử dụng phiên bản gỡ lỗi của malloc / miễn phí. Bọc chúng và viết của riêng bạn nếu cần thiết. Rất nhiều niềm vui!

Phiên bản tôi sử dụng thêm các byte bảo vệ trước và sau mỗi lần phân bổ và duy trì một danh sách "được phân bổ" để kiểm tra miễn phí các đoạn được giải phóng. Điều này bắt hầu hết các lỗi tràn bộ đệm và nhiều lỗi "miễn phí".

Một trong những nguồn tham nhũng quỷ quyệt nhất là tiếp tục sử dụng một đoạn sau khi nó đã được giải phóng. Miễn phí nên lấp đầy bộ nhớ đã giải phóng bằng một mẫu đã biết (theo truyền thống, 0xDEADBEEF) Nó giúp nếu các cấu trúc được phân bổ bao gồm phần tử "số ma thuật" và tự do bao gồm kiểm tra số ma thuật phù hợp trước khi sử dụng cấu trúc.


1
Valgrind nên bắt hai lần tự do / sử dụng dữ liệu miễn phí, phải không?
Robin

Viết loại quá tải này cho mới / xóa đã giúp tôi xác định được nhiều vấn đề hỏng bộ nhớ. Đặc biệt là các byte bảo vệ được xác minh khi xóa và gây ra một điểm ngắt kích hoạt chương trình tự động đưa tôi vào trình gỡ lỗi.
Emily L.

3

Để diễn giải những gì bạn nói trong câu hỏi của bạn, không thể đưa ra câu trả lời dứt khoát. Điều tốt nhất chúng ta có thể làm là đưa ra những gợi ý về những thứ cần tìm và các công cụ và kỹ thuật.

Một số đề xuất sẽ có vẻ ngây thơ, khác có thể áp dụng nhiều hơn, nhưng hy vọng một trong những gợi ý bạn có thể theo dõi. Tôi phải nói rằng câu trả lời của david.pfx có lời khuyên và đề xuất hợp lý.

Từ các triệu chứng

  • với tôi nó có vẻ như là một bộ đệm tràn ngập.

  • một vấn đề liên quan là sử dụng dữ liệu ổ cắm không được định giá làm chỉ mục hoặc khóa, v.v.

  • có thể là bạn đang sử dụng một biến toàn cầu ở một nơi nào đó, hoặc có một toàn cầu và cục bộ có cùng tên, hoặc bằng cách nào đó dữ liệu của một người chơi can thiệp vào một người khác?

Như với nhiều lỗi, có lẽ bạn đang đưa ra một giả định không hợp lệ ở đâu đó. Hoặc có thể nhiều hơn một. Nhiều lỗi tương tác rất khó phát hiện.

  • Có phải mọi biến đều có một mô tả? Và bạn có thể xác định một xác nhận hợp lệ?
    Nếu không thêm chúng, hãy quét qua mã để thấy rằng mỗi biến dường như được sử dụng chính xác. Thêm sự khẳng định đó bất cứ nơi nào nó có ý nghĩa.

  • Gợi ý để thêm nhiều xác nhận là một điều tốt: nơi đầu tiên để đặt chúng là trên mọi điểm nhập hàm. Xác thực các đối số và bất kỳ trạng thái toàn cầu có liên quan.

  • Tôi sử dụng nhiều nhật ký để gỡ lỗi mã chạy dài / không đồng bộ / thời gian thực.
    Một lần nữa, chèn một bản ghi nhật ký trên mỗi cuộc gọi chức năng.
    Nếu các tệp nhật ký quá lớn, các chức năng ghi nhật ký có thể ngắt / chuyển đổi các tệp / v.v ...
    Sẽ hữu ích nhất nếu các thông điệp nhật ký thụt vào với độ sâu của hàm gọi.
    Tệp nhật ký có thể hiển thị cách một lỗi lan truyền. Hữu ích khi một đoạn mã thực hiện một cái gì đó không hoàn toàn đúng, hoạt động như một quả bom hành động bị trì hoãn.

Nhiều người có mã đăng nhập nhà riêng của họ phát triển. Tôi có một hệ thống nhật ký macro C cũ ở đâu đó và có thể là phiên bản C ++ ...


3

Tất cả những gì đã được nói trong các câu trả lời khác là rất phù hợp. Một điều quan trọng được đề cập một phần bởi ddyer là gói malloc / miễn phí có lợi ích. Anh ấy đề cập đến một vài thứ nhưng tôi muốn thêm một công cụ gỡ lỗi rất quan trọng vào đó: bạn có thể đăng nhập mọi malloc / free vào một tệp bên ngoài cùng với một vài dòng callstack (hoặc toàn bộ callstack nếu bạn quan tâm). Nếu bạn cẩn thận, bạn có thể dễ dàng thực hiện việc này khá nhanh và sử dụng nó trong sản xuất nếu có.

Từ những gì bạn mô tả, dự đoán cá nhân của tôi là bạn có thể giữ một tham chiếu đến một con trỏ ở đâu đó để giải phóng bộ nhớ và cuối cùng có thể giải phóng một con trỏ không còn thuộc về bạn hoặc viết cho nó. Nếu bạn có thể suy ra một phạm vi kích thước để theo dõi bằng kỹ thuật trên, bạn sẽ có thể thu hẹp đáng kể việc ghi nhật ký. Mặt khác, một khi bạn tìm thấy những gì bộ nhớ đã bị hỏng, bạn có thể tìm ra mô hình malloc / miễn phí dẫn đến nó khá dễ dàng từ các bản ghi.

Một lưu ý quan trọng là như bạn đề cập, việc thay đổi bố cục bộ nhớ có thể che giấu vấn đề. Do đó, điều rất quan trọng là việc ghi nhật ký của bạn không phân bổ (nếu bạn có thể!) Hoặc càng ít càng tốt. Điều này sẽ giúp tái sản xuất nếu nó liên quan đến bộ nhớ. Nó cũng sẽ giúp nếu nó càng nhanh càng tốt nếu vấn đề liên quan đến đa luồng.

Điều quan trọng nữa là bạn bẫy phân bổ từ các thư viện bên thứ 3 để bạn cũng có thể đăng nhập chúng đúng cách. Bạn không bao giờ biết nó có thể đến từ đâu.

Thay thế cuối cùng, bạn cũng có thể tạo một công cụ phân bổ tùy chỉnh nơi bạn phân bổ ít nhất 2 trang cho mỗi phân bổ và hủy ánh xạ chúng khi bạn rảnh (căn chỉnh phân bổ cho một ranh giới trang, phân bổ một trang trước và đánh dấu nó là không thể truy cập hoặc căn chỉnh phân bổ ở cuối trang và phân bổ một trang sau và đánh dấu là không thể truy cập được). Đảm bảo không sử dụng lại các địa chỉ bộ nhớ ảo đó để phân bổ mới trong ít nhất một thời gian. Điều này ngụ ý bạn sẽ cần phải tự quản lý bộ nhớ ảo của mình (dự trữ và sử dụng nó theo ý muốn). Lưu ý rằng điều này sẽ làm giảm hiệu suất của bạn và có thể sẽ sử dụng một lượng bộ nhớ ảo đáng kể tùy thuộc vào số lượng phân bổ bạn cung cấp. Để giảm thiểu điều này, nó sẽ hữu ích nếu bạn có thể chạy trong 64 bit và / hoặc giảm phạm vi phân bổ cần điều này (dựa trên kích thước). Valgrind rất có thể đã làm điều này nhưng nó có thể quá chậm để bạn có thể bắt kịp vấn đề với nó. Làm điều này chỉ cho một vài kích thước hoặc đối tượng (nếu bạn biết, bạn chỉ có thể sử dụng bộ cấp phát đặc biệt cho các đối tượng đó) sẽ đảm bảo hiệu suất bị ảnh hưởng tối thiểu.


0

Hãy thử đặt một điểm quan sát trên địa chỉ bộ nhớ mà nó gặp sự cố. GDB sẽ phá vỡ theo hướng dẫn gây ra bộ nhớ không hợp lệ. Sau đó, với dấu vết trở lại, bạn có thể thấy mã của mình gây ra tham nhũng. Đây có thể không phải là nguồn gốc của tham nhũng nhưng việc lặp lại quan điểm về mỗi tham nhũng có thể dẫn đến nguồn gốc của vấn đề.

Nhân tiện, vì câu hỏi được gắn thẻ C ++, hãy xem xét sử dụng các con trỏ được chia sẻ chăm sóc quyền sở hữu bằng cách duy trì số tham chiếu và xóa bộ nhớ một cách an toàn sau khi con trỏ đi ra khỏi phạm vi. Nhưng sử dụng chúng một cách thận trọng vì chúng có thể gây ra bế tắc trong việc sử dụng phụ thuộc vòng tròn hiếm gặp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.