Tôi không hiểu sự khác biệt giữa con trỏ treo và rò rỉ bộ nhớ. Hai thuật ngữ này liên quan như thế nào?
Tôi không hiểu sự khác biệt giữa con trỏ treo và rò rỉ bộ nhớ. Hai thuật ngữ này liên quan như thế nào?
Câu trả lời:
Một con trỏ lơ lửng trỏ đến bộ nhớ đã được giải phóng. Bộ nhớ không còn được phân bổ. Cố gắng truy cập nó có thể gây ra lỗi Phân đoạn.
Cách phổ biến để kết thúc với một con trỏ treo lơ lửng:
char *func()
{
char str[10];
strcpy(str, "Hello!");
return str;
}
//returned pointer points to str which has gone out of scope.
Bạn đang trả về một địa chỉ là một biến cục bộ, địa chỉ này sẽ vượt ra khỏi phạm vi bởi điều khiển thời gian được trả lại cho hàm gọi. (Hành vi không xác định)
Một ví dụ về con trỏ treo lơ lửng phổ biến khác là truy cập vào một vị trí bộ nhớ thông qua con trỏ, sau khi phần mềm miễn phí đã được gọi một cách rõ ràng trên bộ nhớ đó.
int *c = malloc(sizeof(int));
free(c);
*c = 3; //writing to freed location!
Một rò rỉ bộ nhớ là bộ nhớ mà chưa được giải thoát, không có cách nào để truy cập (hoặc giải phóng nó) bây giờ, khi không có những cách để có được nó nữa. (Ví dụ: một con trỏ là tham chiếu duy nhất đến vị trí bộ nhớ được cấp phát động (và không được giải phóng) hiện trỏ đến một nơi khác.)
void func(){
char *ch = malloc(10);
}
//ch not valid outside, no way to access malloc-ed memory
Char-ptr ch là một biến cục bộ nằm ngoài phạm vi ở cuối hàm, làm rò rỉ 10 byte được cấp phát động .
Bạn có thể coi đây là những mặt đối lập của nhau.
Khi bạn giải phóng một vùng bộ nhớ, nhưng vẫn giữ một con trỏ đến nó, con trỏ đó đang treo lơ lửng:
char *c = malloc(16);
free(c);
c[1] = 'a'; //invalid access through dangling pointer!
Khi bạn làm mất con trỏ, nhưng vẫn giữ bộ nhớ được cấp phát, bạn bị rò rỉ bộ nhớ:
void myfunc()
{
char *c = malloc(16);
} //after myfunc returns, the the memory pointed to by c is not freed: leak!
Con trỏ treo là một con trỏ có giá trị (không phải NULL) tham chiếu đến một số bộ nhớ không hợp lệ cho loại đối tượng bạn mong đợi. Ví dụ: nếu bạn đặt một con trỏ cho một đối tượng thì ghi đè lên bộ nhớ đó bằng một thứ khác không liên quan hoặc giải phóng bộ nhớ nếu nó được cấp phát động.
Một rò rỉ bộ nhớ là khi bạn tự động phân bổ bộ nhớ từ đống nhưng không bao giờ giải phóng nó, có thể là vì bạn bị mất tất cả các tham chiếu tới nó.
Chúng có liên quan với nhau ở chỗ chúng đều là các tình huống liên quan đến con trỏ được quản lý sai, đặc biệt là liên quan đến bộ nhớ được cấp phát động. Trong một tình huống (con trỏ treo lơ lửng), bạn có thể đã giải phóng bộ nhớ nhưng sau đó cố gắng tham chiếu đến nó; trong trường hợp khác (rò rỉ bộ nhớ), bạn đã quên giải phóng bộ nhớ hoàn toàn!
Con trỏ nguy hiểm
Nếu bất kỳ con trỏ nào đang trỏ đến địa chỉ bộ nhớ của bất kỳ biến nào nhưng sau khi một số biến đã bị xóa khỏi vị trí bộ nhớ đó trong khi con trỏ vẫn đang trỏ vị trí bộ nhớ đó. Con trỏ như vậy được gọi là con trỏ treo và vấn đề này được gọi là vấn đề con trỏ treo.
#include<stdio.h>
int *call();
void main(){
int *ptr;
ptr=call();
fflush(stdin);
printf("%d",*ptr);
}
int * call(){
int x=25;
++x;
return &x;
}
Đầu ra: Giá trị rác
Lưu ý: Trong một số trình biên dịch, bạn có thể nhận được thông báo cảnh báo trả về địa chỉ của biến cục bộ hoặc tạm thời
Giải thích: biến x là biến cục bộ. Phạm vi và thời gian tồn tại của nó nằm trong lời gọi hàm do đó sau khi trả về địa chỉ của x biến x đã trở thành dead và con trỏ vẫn đang trỏ ptr vẫn đang trỏ đến vị trí đó.
Giải pháp của vấn đề này: Làm cho biến x là biến tĩnh. Nói cách khác, chúng ta có thể nói một con trỏ có đối tượng trỏ đã bị xóa được gọi là con trỏ treo.
Bộ nhớ bị rò rỉ
Trong khoa học máy tính, rò rỉ bộ nhớ xảy ra khi một chương trình máy tính quản lý sai phân bổ bộ nhớ. Như đơn giản, chúng tôi đã cấp phát bộ nhớ và không Miễn phí thuật ngữ ngôn ngữ khác nói rằng không phát hành nó gọi là rò rỉ bộ nhớ, nó gây tử vong cho ứng dụng và sự cố bất ngờ.
Con trỏ giúp tạo phạm vi do người dùng xác định cho một biến, được gọi là Biến động. Biến động có thể là biến đơn hoặc nhóm biến cùng loại ( array
) hoặc nhóm biến khác loại ( struct
). Phạm vi biến cục bộ mặc định bắt đầu khi điều khiển đi vào một chức năng và kết thúc khi điều khiển ra khỏi chức năng đó. Phạm vi có thể thay thế toàn cầu mặc định bắt đầu khi thực thi chương trình và kết thúc khi chương trình kết thúc.
Nhưng phạm vi của một biến động do một con trỏ nắm giữ có thể bắt đầu và kết thúc tại bất kỳ thời điểm nào trong quá trình thực thi chương trình, điều này phải do lập trình viên quyết định. Nguy hiểm và rò rỉ bộ nhớ chỉ xuất hiện nếu một lập trình viên không xử lý hết phạm vi.
Rò rỉ bộ nhớ sẽ xảy ra nếu một lập trình viên không viết mã ( free
của con trỏ) cho cuối phạm vi cho các biến động. Bất kỳ cách nào sau khi chương trình thoát khỏi bộ nhớ quy trình hoàn chỉnh sẽ được giải phóng, tại thời điểm đó bộ nhớ bị rò rỉ này cũng sẽ được giải phóng. Nhưng nó sẽ gây ra một vấn đề rất nghiêm trọng cho một quy trình đang chạy trong thời gian dài.
Khi phạm vi của biến động kết thúc (giải phóng), NULL
nên được gán cho biến con trỏ. Nếu không, nếu mã truy cập sai, hành vi không xác định sẽ xảy ra. Vì vậy, con trỏ treo lơ lửng không là gì khác ngoài một con trỏ trỏ đến một biến động có phạm vi đã hoàn thành.
Rò rỉ bộ nhớ : Khi có một vùng bộ nhớ trong một heap nhưng không có biến nào trong ngăn xếp trỏ đến vùng nhớ đó.
char *myarea=(char *)malloc(10);
char *newarea=(char *)malloc(10);
myarea=newarea;
Con trỏ nguy hiểm : Khi một biến con trỏ trong ngăn xếp nhưng không có bộ nhớ trong heap.
char *p =NULL;
Một con trỏ treo lơ lửng cố gắng truy cập mà không phân bổ không gian sẽ dẫn đến lỗi phân đoạn.
Một con trỏ trỏ đến một vị trí bộ nhớ đã bị xóa (hoặc giải phóng) được gọi là con trỏ treo.
#include <stdlib.h>
#include <stdio.h>
void main()
{
int *ptr = (int *)malloc(sizeof(int));
// After below free call, ptr becomes a
// dangling pointer
free(ptr);
}
để biết thêm thông tin bấm vào ĐÂY
Một con trỏ trỏ đến một vị trí bộ nhớ đã bị xóa (hoặc giải phóng) được gọi là con trỏ treo. Có ba cách khác nhau mà Pointer hoạt động như một con trỏ treo.
- Khử phân bổ bộ nhớ
- Gọi hàm
- Biến vượt ra ngoài phạm vi
—— từ https://www.geeksforgeeks.org/dangling-void-null-wild-pointers/