2011-10-05 39 views
8

Tôi có một mã mà tôi sử dụng một con trỏ để truy cập vào một số datablock. Trong một số trường hợp hiếm hoi, một vài thành viên của datablock trống, và kết quả là con trỏ trở nên lơ lửng. Trong thực tế, tôi có được con trỏ chính xác nhưng chương trình bị treo khi cố gắng làm điều gì đó với con trỏ.Có cách nào để kiểm tra xem con trỏ có đang lơ lửng không?

Lời khuyên thông thường là tránh loại sử dụng này. Nhưng thật đáng buồn, khuôn khổ tôi sử dụng yêu cầu tôi sử dụng loại phương pháp truy cập dữ liệu này.

Có cách nào tôi có thể "kiểm tra" nếu con trỏ không hợp lệ trước khi thực hiện bất kỳ thao tác nào với nó? Kiểm tra rằng con trỏ không bằng NULL đã không hoạt động, rõ ràng. Tôi cũng đã thử điều này:

try 
{ 
    CString csClassName = typeid(*pMyPointer).name(); // Check error condition 
    // The line below fails due to dangling pointer (data block is not valid). 
    hr = pMyPointer->MyPointerMethod(); 
} 
catch(bad_typeid) 
{ 
    return E_FAIL; 
} 
catch(...) 
{ 
    return E_FAIL; 
} 

Đây có phải là cách chính xác không?

Trả lời

5

Không có cách nào để kiểm tra xem con trỏ thô có hợp lệ hay không. Các con trỏ không hợp lệ không được đảm bảo không thành công khi bạn truy cập chúng. Thay vì sử dụng một con trỏ thô, bạn cần sử dụng một số hình thức con trỏ thông minh.

+0

Con trỏ của tôi phải tĩnh đối với lớp .. có ổn không nếu tôi sử dụng con trỏ thông minh? – Nikhil

+0

Không có vấn đề gì cả. Bạn cần phải xem ra các vấn đề an toàn chủ đề nhưng đó là không có khác nhau cho một con trỏ thông minh vs một con trỏ thô. –

+2

Tôi không nghĩ nó quan trọng. Điều duy nhất làm phiền tôi là liệu khuôn khổ của bạn có thể tự làm cho con trỏ của bạn lúng túng mà không cần thông báo trước. Hãy xem, bạn sẽ phải giải nén con trỏ thô ra khỏi con trỏ thông minh và chuyển nó vào khung công tác của bạn. Nếu nó đảm bảo rằng con trỏ sẽ vẫn còn hiệu lực sau khi cuộc gọi, hoặc bạn sẽ được thông báo nếu nó trở thành không hợp lệ - tốt, đi cho nó. – Septagram

7

Tôi nghĩ bạn đang nhìn sai hướng. Bạn có thể có một lỗi mà bạn không phải là chính xác khởi tạo con trỏ, xóa các đối tượng quá sớm và cố gắng tái sử dụng con trỏ sau khi nó đã bị xóa hoặc một cái gì đó giống nhau. Nếu đúng như vậy, bạn nên tập trung vào việc xác định lý do tại sao điều đó đang xảy ra và sửa lỗi, thay vì cố gắng tìm cách ẩn lỗi.

Do cách tiếp cận mà bạn đang sử dụng với toán tử typeid, câu trả lời là nó không hợp lệ. Đối với các đối tượng kiểu không chứa hàm ảo, toán tử typeid được giải quyết tại thời gian biên dịch dựa trên loại tĩnh của con trỏ. Đối với các đối tượng có chứa ít nhất một hàm ảo, nó được giải quyết trong thời gian chạy, nhưng gọi typeid(p) với một con trỏ không hợp lệ là hành vi không xác định và theo cách giống như nó hoạt động, nó có thể bị lỗi.

Việc sử dụng các con trỏ thông minh đã được đề xuất, có thể phụ thuộc vào thư viện thực sự làm gì và bạn có thể truyền con trỏ thông minh vào mọi lúc hay không. Nói chung, bạn nên sử dụng con trỏ thông minh để quản lý bộ nhớ, và điều này sẽ đảm bảo rằng con trỏ sẽ được khởi tạo chính xác (khắc phục nếu sự cố đang khởi tạo) và vì bạn không còn delete theo cách thủ công nữa, rất có thể là vấn đề là việc xóa sớm sẽ không còn xảy ra nữa. Nhưng lưu ý rằng trong khi điều này có thể giải quyết vấn đề, tôi vẫn nghĩ rằng bạn cần phải hiểu tại sao con trỏ không hợp lệ trong ứng dụng của bạn, vì đó có thể là một triệu chứng của một vấn đề lớn hơn.

Bây giờ, trên câu hỏi ban đầu về cách kiểm tra xem con trỏ có đang lơ lửng hay không, bạn không thể làm điều đó trong chương trình, nhưng bạn có thể chạy chương trình của bạn bên trong bộ nhớ gỡ rối (valgrind trong linux, Purify hoặc một bộ khác trong linux) và công cụ sẽ có thể giúp bạn xác định xem con trỏ chưa bao giờ được khởi tạo hay nếu bạn đã giải phóng bộ nhớ cho hệ thống trước khi sử dụng không chính xác.

+0

Cảm ơn lời giải thích chi tiết của bạn.Tôi có thể hiểu rằng tôi nên tìm một giải pháp thay vì ẩn lỗi ... Nhưng có một lỗ hổng trong khung được thiết kế mà tôi không thể thay đổi trong thời gian ngắn. Tôi đang tìm cách giải quyết cho thời gian Tôi đã thử với con trỏ thông minh nhưng nó cũng không thành công. – Nikhil

1

Bạn không cần con trỏ thông minh. Họ chỉ là một cách tiếp cận có thể để đối phó với vấn đề này.

Bạn có thể sử dụng tham chiếu đối ứng: Trong đối tượng được tham chiếu (referencee), danh sách tham chiếu quay lại các đối tượng tham chiếu đến nó (tham chiếu). Khi đó là thời gian để deallocate referencee, đầu tiên chạy qua danh sách referencers và thiết lập bất kỳ thuộc tính nào trong đó chúng sử dụng để trỏ tới referencee, null (thông thường bạn muốn biết trước thuộc tính nào sẽ là), sau đó deallocate tham chiếu.

Các vấn đề liên quan