2013-08-01 22 views
32

Tôi biết đây là câu hỏi khá phổ biến, nhưng vẫn còn mới đối với tôi!Con trỏ lơ lửng là gì

Tôi không hiểu khái niệm về con trỏ lơ lửng, googling xung quanh, và viết phương pháp kiểm tra để tìm một ... Tôi chỉ tự hỏi đây là một con trỏ lơ lửng? Như bất kỳ ví dụ nào tôi tìm thấy đã trả lại một cái gì đó, ở đây tôi đang thử một cái gì đó tương tự! Cảm ơn!

void foo(const std::string name) 
{ 
    new_foo(name.c_str()); ///// will it be Dangling pointer?!, with comments/Answer 
          ///// it could be if in new_foo, I store name into Global. 
          ///// Why?! And what is safe then? 
} 

void new_foo(const char* name) 
{ 
    ... print name or do something with name... 
} 
+0

* "?! Nó sẽ được lơ lửng con trỏ, với ý kiến ​​/ trả lời đó là" * - Không, nó không phải là. Không có con trỏ lơ lửng trong ví dụ đầu tiên của bạn. Những gì bạn đang làm ở đó là hoàn hảo, 100% an toàn và chính xác. –

+0

Tôi không thấy làm thế nào bạn có thể có một con trỏ * lơ lửng * ... mà không có con trỏ *. –

+0

@TheOtherGuy Tôi có nghĩa là, không có const char * ... mang cùng const std :: string –

Trả lời

38

Một con trỏ tòn ten là một con trỏ trỏ không hợp lệ dữ liệu hoặc dữ liệu mà không có giá trị nữa, ví dụ:

Class *object = new Class(); 
Class *object2 = object; 

delete object; 
object = nullptr; 
// now object2 points to something which is not valid anymore 

Điều này có thể xảy ra ngay cả trong đống phân bổ các đối tượng:

Object *method() { 
    Object object; 
    return &object; 
} 

Object *object2 = method(); 
// object2 points to an object which has been removed from stack after exiting the function 

Con trỏ được trả về c_str có thể trở thành không hợp lệ nếu chuỗi được sửa đổi sau đó hoặc bị hủy. Trong ví dụ của bạn, bạn dường như không sửa đổi nó, nhưng vì nó không rõ ràng những gì bạn sẽ làm với const char *name nó không thể biết nó mã của bạn vốn đã an toàn hay không.

Ví dụ: nếu bạn lưu con trỏ ở đâu đó và sau đó chuỗi tương ứng bị hủy, con trỏ sẽ không hợp lệ. Nếu bạn sử dụng const char *name chỉ trong phạm vi new_foo (ví dụ, cho mục đích in) thì con trỏ sẽ vẫn hợp lệ.

+0

Bạn cũng có thể thêm rằng ví dụ của OP không treo lơ lửng – Angew

+0

IIRC nếu bạn sửa đổi nội dung của chuỗi sau đó bạn làm mất hiệu lực con trỏ được trả về bởi 'c_str()' để nó * có thể * được coi là lơ lửng. – Jack

+0

Nhưng chuỗi không được sửa đổi. Và không có cách nào để nó được sửa đổi một cách hợp pháp, ngay cả trong một ứng dụng đa luồng. –

10

Con trỏ lơ lửng là con trỏ (không phải NULL) trỏ đến vùng bộ nhớ chưa được phân bổ (đã giải phóng).

Ví dụ trên phải đúng vì chuỗi không được sửa đổi thông qua new_foo.

+0

... nhấn mạnh "* đã được giải phóng *"! – alk

+0

@ Miklós Homolya "const" của nó .. những gì bạn có nghĩa là sửa đổi trong new_foo ?! –

+0

Việc sử dụng "const" là tính năng front-end (trình biên dịch), có thể được khắc phục bằng một const_cast. Vấn đề là làm thế nào để có được - theo một cách tuân thủ tiêu chuẩn - một tham chiếu đến biến ngăn xếp 'tên', bởi vì mã của hàm 'foo' đã được đưa ra. –

2

Như một vấn đề về phong cách, tôi giải thích một con trỏ lơ lửng là "một con trỏ vẫn còn tồn tại, mặc dù đối tượng nó trỏ đến không còn tồn tại".

Trong trường hợp của bạn, con trỏ name tồn tại trong một khoảng thời gian ngắn hơn mà đối tượng trỏ đến. Vì vậy, nó không bao giờ lúng túng.

Bên trong lớp C++ phổ biến, con trỏ lơ lửng trong một khoảng thời gian rất ngắn, bên trong trình phá hủy. Đó là bởi vì câu lệnh delete là trước } cuối cùng của hàm hủy, trong khi chính con trỏ không còn tồn tại ở số } cuối cùng nữa. Nếu bạn không muốn lo lắng về điều này, hãy sử dụng ví dụ: unique_ptr<T>. Con trỏ T* sẽ treo lơ lửng trong một khoảng thời gian rất ngắn bên trong trình phá hủy unique_ptr::~unique_ptr, điều này hoàn toàn an toàn.

2

Lấy từ here. Mặc dù, ngay cả khi điều này là cho C, nó là như nhau cho C + +.

Dangling Pointer

Nếu bất kỳ con trỏ trỏ địa chỉ bộ nhớ của bất kỳ biến nhưng sau khi một số biến đã bị xóa từ vị trí đó bộ nhớ trong khi con trỏ vẫn chỉ vị trí bộ nhớ như vậy. Con trỏ như vậy được gọi là con trỏ lơ lửng và vấn đề này được gọi là vấn đề con trỏ lơ lửng.

Ban đầu

enter image description here

Sau

enter image description here

Ví dụ

#include<stdio.h> 

int *call(); 
int main(){ 

int *ptr; 
ptr=call(); 

fflush(stdin); 
printf("%d",*ptr); 
return 0; 
} 
int * call(){ 

int x=25; 
++x; 

return &x; 
} 

Đầu ra của nó sẽ là rác vì biến x là biến cục bộ. Phạm vi và tuổi thọ của nó nằm trong hàm gọi do đó sau khi trở về địa chỉ của x biến x đã trở thành chết và con trỏ vẫn trỏ ptr vẫn trỏ đến vị trí đó.

-2

Con trỏ lơ lửng và vấn đề con trỏ lơ lửng Nếu bất kỳ con trỏ trỏ đến địa chỉ bộ nhớ của bất kỳ biến nào nhưng sau một số biến đã bị xóa khỏi vị trí bộ nhớ đó trong khi con trỏ vẫn trỏ đến vị trí bộ nhớ đó.

Con trỏ đó được gọi là con trỏ lơ lửng và vấn đề phát sinh tại thời điểm đó được gọi là vấn đề con trỏ lơ lửng.

Dưới đây là một số ví dụ: Dangling Pointer and dangling pointer problem