Nguồn : http://diendan.congdongcviet.com/threads/t36221::ban-chat-cua-viec-cap-phat-bo-nho-dong-giai-phong-bo-nho.cpp bài viết khá hay nên minh copy qua đây
1. Dẫn nhập
Bộ nhớ là 1 tài nguyên quan trọng trong hệ thống , được phân phối điều phối phức tạp.
ở đây, chúng ta sẽ xét tương quan như sau cho dễ hiểu : đất là 1 tài nguyên quý giá trong thành phố và được điều phối bởi sở tài nguyên môi trường
(coi như thế, giờ hình như nó thuộc sở nhà đất thì phải,nói tóm lại là sở quản lí)
2. Cấp phát bộ nhớ :
Bộ nhớ quan trọng như thế ko thể tùy tiện sử dụng , vì trong máy có nhiều tiếng trình cần bộ nhớ, tùy tiện sử dụng thì lấy đâu ra mà dùng ????
ai cũng cần có đất, cứ tùy tiện lấy gì cần gì sở quản lý, như thế sẽ có người không có đất mà dùng ???
Cấp phát bộ nhớ hoạt động như thế nào : bản chất là trao quyền sử dụng.
hôm nay 1 người (1 con trỏ) xin cấp phát (malloc, new) 1 vùng đất, anh ta được trao quyền sử dụng 1 vùng đất đó.
Khi này :
+ Có thể trên mảnh đất này đang trống rỗng (toàn null) nhưng cũng có thể trên đó đầy cỏ rác,hoa màu hoặc nhà cửa do người trước đó sử dụng vẫn còn . (điều này đối với anh ta mà nói nó hoàn toàn là ngẫu nhiên, ko ai có thể khẳng định được cả)
>>>>> khi ta xin cấp phát xong thì vùng nhớ đó hoàn toàn có giá trị ngẫu nhiên
+ Nếu như khi anh ta xin cấp phát mà có đút lót để ra thêm điều kiện hoặc trước đó anh ta có thuê thêm 1 người quét dọn xây sửa thì anh sẽ có được 1 mảnh đất có sẵn cái anh ta muốn
>>>> khi ta cấp phát đi cùng với ép buộc sẽ được vùng nhớ có giá trị như ta mong muốn
ví dụ
<<<<<<<< toàn bộ điều này là đáp án tại sao khi cấp phát bộ nhớ lại có giá trị ngẫu nhiên
3. Giải phóng bộ nhớ như thế nào
Anh ta dùng xong đất rồi, ko cần nữa, đem trả quyền sử dụng mảnh đất lại cho khổ chủ.
Giải bộ nhớ hoạt động như thế nào : bản chất là trả lại quyền sử dụng
khi này :
+ sở sẽ thu lại quyền sử dụng đất của anh, thế là đủ rồi, sở ko cần phải động chạm sửa chữa lại gì vùng đất đó. Nên khi đó dù vùng đất đó đã được giải phóng nhưng mà hoa màu của a ta trên đó thì vẫn còn, ko có biến mất được
điều này giải thích tại sao khi mà trong 1 số hệ điều hành đời cổ, (các bạn lính mới bây giờ chắc không gặp) nhiều bạn thử giải phóng bộ nhớ rồi, delete rồi, free rồi mà khi in thử ra vẫn thấy kết quả như thế .
đơn giản thôi, a ta trả lại mảnh đất đó, nhưng chưa có ai thuê nó cả, chưa có ai sử dụng nên hôm sau ra xem thử thì nó vẫn như hôm trước khi a ta trả lại
Các bạn đọc rõ chú ý ở dưới rồi hẵng hỏi thêm về câu này nhé.
Và các bạn phải chú ý là quyền sử dụng đất mới là cái được quan tâm duy nhất của vấn đề này
thì giá trị trong a và b là địa chỉ của vùng nhớ được cấp phát. địa chỉ này sẽ được lưu lại trong sở, sở sẽ dùng cái số địa chỉ này để hiểu là quyền sử dụng đất khi giải phóng
tiếp theo
2 câu lệnh này ko có làm thay đổi giá trị của a và ba và b vẫn trỏ vào mảnh đất đấy. ok ? Và càng ko can thiệp vào vùng nhớ mà a ,b trỏ đến, cái duy nhất mà nó làm là xác nhận vùng nhớ đó đã được trả lại, đang rảnh rỗi, có thể cho thuê tiếp.
<<< điều này giải thích cho cách hiểu sai lầm của 1 số bạn mới học đối với việc cấp phát và giải phóng
4. Memory leak
Câu hỏi mở rộng :
như thế này có phải là giải phóng ko
ở trong C (not java, java khác) thì :
câu trả lời là không , bạn đã hiểu sai lầm hoàn toàn về việc giải phóng rồi, bạn nên đọc kĩ lại phần giải phóng để hiểu tại sao.
như thế này chính là :
anh ta đánh mất cái quyền sử dụng đất của mình, kết quả là vùng đất đó ko được sở lấy về, sau nhiều lần như thế thì tài nguyên đất của sở càng ngày càng ít đi, hiện tượng này gọi mà memory leak
Sau khi chương trình kết thúc , việc bộ nhớ xin cấp phát có được tự giải phóng hay ko thì tùy thuộc vào cài đặt của trình biên dịch và hệ điều hành. Chúng ta có 2 khả năng · Khả năng 1 : trong phần khởi động (trước khi vào function main() ), program xin một khối memory cuả system gọi là XXXX và mỗi lần malloc được gọi thì cấp pháp một phần memory cuả XXXX cho malloc. Do đó, khi program exit thì trả XXXX về cho system là xong. Trong trường hợp này không bị mất memory
· Khả năng 2 : mỗi lần malloc được gọi thì xin memory từ system . Trường hợp này có thể memory không trả về cho system. Lúc này chương trình sẽ bị gọi là có memory leak.Như vậy sau vài lần chạy sẽ ko còn memory để cấp phát nữa
Đó là giải thích tại sao có nhiều chương trình chạy xong, thoát ra rồi, f5 mấy lần rồi mà máy vẫn cứ ì ì ì ra..........
5. Trên đây là cách lý thuyết cơ bản dành cho các bạn mới học, nó được áp dụng đối với lập trình trên console, (cấp sở tài nguyên thôi)
trong windows nó cũng như thế thôi nhưng mà nó có thêm nhiều quy tắc rằng buộc chặt chẽ hơn rất nhiều (cấp bộ tài nguyên và môi trường, phải khác chứ)
Muốn biết thêm về bộ nhớ thì xem chap 1 của tut dưới đây :
Portable Executable File Format
Update 9/9/10
Câu hỏi
Nhân tiện cho em hỏi, nếu mình khai báo 1 mảng có thể có rất nhiều phần tử thì bộ nhớ của nó sẽ được lấy từ đâu ra (Ổ cứng, Ram.... Hay là một cái gì đó mà em không biết :P). Khi em khai báo 1 mảng int a[1000000] thì nó báo là "Array size too large". Mới có 1000000 phần tử nó đã coi là lớn thì những bài toán thực tế vài triệu phần tử liền thì phải làm thế nào? hix
Trả lời
int a[1000000] ; khai báo ở đâu ?
em khai báo ở sở (tức là khai báo dạng local, trong các hàm )thì sở nó xin vùng nhớ ở stack segment, mà stack segment thì đây (trong ảnh, nhỏ gọn thế này, liệu nó có cho em vùng lớn thế kia ko 1000000*4byte)
Click vào ảnh để xem hình đẩy đủ
đối với các bài toán cần nhiều vùng nhớ 1 cách kinh khủng thì ta thường dùng các hàm api về malloc để lấy các vùng nhớ ở free store được bộ (os-hệ điều hành) cấp phát,
và 1 điều ko kém phần quan trọng đó là ta nên xây dựng những giải thuật thật thông minh chứ ko phải là load tràn hết lên bộ nhớ
ví dụ xây dựng trước các phương pháp xử lý các sự kiện có thể xảy ra
giả sử như này, tôi có 1 khối thông tin, để bắt sự kiện "tìm nhân viên mới vào công ti", tôi lập ra 1 temponary, mỗi khi chèn thằng mới vào khối thông tin của tôi, tôi gán thằng temponary này bằng với nhân viên mới, như thế tôi đã có 1 phương pháp sử lí sự kiện tốt rồi đúng ko ???
Update 10/9/10
câu hỏi
Cấp phát động thì nó lấy bộ nhớ từ đâu vậy cà.
"data segment"
Là cái gì thế em dịch là dữ liệu phân đoạn, nghĩa là sao đây, anh langman bận rộn thế :P:P
a. theo giáo trình đại học FPT về OS,theo giáo trình thầy phạm văn ất về tổ thức bộ nhớ, khi tiến trình chạy , bộ nhớ được mô hình thành 4 phần như sau
(trên thực tế, trong windows, môi trường ảo hóa cụ thể này thì có cách tổ chức phức tạp hơn phát triển từ lý thuyết này)
b. đang bận ôn thi ko có time online được
Update 20/11/10
Câu hỏi của quyết 1991 : sự khác nhau giữa malloc và new?
new và malloc khác nhau cực cực kì nhiều đó các pạn à
sơ bộ như sau, chưa phân tích kĩ
malloc là hàm, cấp phát trả về kiểu void *, malloc thì ko gọi hàm tạo
free ko gọi hàm hủy
malloc trả về NULL nếu thất bại
new là toán tử, new gọi hàm tạo, new có thể được đa năng hóa (nạp chồng),
new ném ra exception nếu thất bại
toán tử new và toán tử new[] ko có khả năng realloc
Update tiếp câu hỏi hay 2/3/2010
xin khẳng định lại 1 lần nữa, e đã hiểu hoàn toàn sai lầm, FREE và DEL ko bao giờ thay đổi giá trị của con trỏ, hãy phân việt rõ ràng giữa giá trị của con trỏ và giá trị nó trỏ đến
free nó là void free(void *mem) vậy thì xin hỏi con trỏ mem làm sao có thể thay đổi giá trị qua hàm này (xin hãy đọc bài bản chất con trỏ trong C để hiểu sâu hơn vấn đề này, tip : phân biệt rõ ràng giữa giá trị của mem và giá trị của thằng mà mem trỏ tới)
check lại đoạn code sau đây
điều nữa
giả sử ngay khi em vừa trả , có thằng khác nó đến thuê luôn thì lập tức nó bỏ hoa màu của em đi, trồng hoa màu khác thì em quay lại làm gì còn thời đại này nhanh như ăn cắp ý mà
(windows có bao nhiêu process, thread,? nên việc bị thuê ngay lập tức là quá bình thường, em à, đặc biệt nếu là hàng nằm trên stack thì thay đổi liên tục là bt)
More :
khi em cài hook bắt các API trên window sẽ thấy LocalAlloc, RemoteAlloc,GlobalAlloc... được xài rất nhiều lần trên /1s chứ ko phải (ví dụ nhỏ xem ở hình dưới , đó là chỉ trong 1 tiến trình firefox thôi đó, chứ ko phải xét trên 5x process đang chạy)
tuy nhiên đối với các môi trường cũ, đặc biệt như trên borland C for dos thì hiện tượng free rồi mà còn tài nguyên rất hay xảy ra, có rât rất nhiều người hiểu lầm là lỗi, rồi ... (đã có rất nhiều câu hỏi như thế trong box thắc mắc C). đó là lý do vì sau a phải nhấn mạnh điều đó
1. Dẫn nhập
Bộ nhớ là 1 tài nguyên quan trọng trong hệ thống , được phân phối điều phối phức tạp.
ở đây, chúng ta sẽ xét tương quan như sau cho dễ hiểu : đất là 1 tài nguyên quý giá trong thành phố và được điều phối bởi sở tài nguyên môi trường
(coi như thế, giờ hình như nó thuộc sở nhà đất thì phải,nói tóm lại là sở quản lí)
2. Cấp phát bộ nhớ :
Bộ nhớ quan trọng như thế ko thể tùy tiện sử dụng , vì trong máy có nhiều tiếng trình cần bộ nhớ, tùy tiện sử dụng thì lấy đâu ra mà dùng ????
ai cũng cần có đất, cứ tùy tiện lấy gì cần gì sở quản lý, như thế sẽ có người không có đất mà dùng ???
Cấp phát bộ nhớ hoạt động như thế nào : bản chất là trao quyền sử dụng.
hôm nay 1 người (1 con trỏ) xin cấp phát (malloc, new) 1 vùng đất, anh ta được trao quyền sử dụng 1 vùng đất đó.
Khi này :
+ Có thể trên mảnh đất này đang trống rỗng (toàn null) nhưng cũng có thể trên đó đầy cỏ rác,hoa màu hoặc nhà cửa do người trước đó sử dụng vẫn còn . (điều này đối với anh ta mà nói nó hoàn toàn là ngẫu nhiên, ko ai có thể khẳng định được cả)
>>>>> khi ta xin cấp phát xong thì vùng nhớ đó hoàn toàn có giá trị ngẫu nhiên
+ Nếu như khi anh ta xin cấp phát mà có đút lót để ra thêm điều kiện hoặc trước đó anh ta có thuê thêm 1 người quét dọn xây sửa thì anh sẽ có được 1 mảnh đất có sẵn cái anh ta muốn
>>>> khi ta cấp phát đi cùng với ép buộc sẽ được vùng nhớ có giá trị như ta mong muốn
ví dụ
PHP Code:
int *a=new int(4);int *b=(int*)malloc(1000);memset(b.....);
static int x[1000];
static int y[10]={1,2,3,4,5,6};
3. Giải phóng bộ nhớ như thế nào
Anh ta dùng xong đất rồi, ko cần nữa, đem trả quyền sử dụng mảnh đất lại cho khổ chủ.
Giải bộ nhớ hoạt động như thế nào : bản chất là trả lại quyền sử dụng
khi này :
+ sở sẽ thu lại quyền sử dụng đất của anh, thế là đủ rồi, sở ko cần phải động chạm sửa chữa lại gì vùng đất đó. Nên khi đó dù vùng đất đó đã được giải phóng nhưng mà hoa màu của a ta trên đó thì vẫn còn, ko có biến mất được
điều này giải thích tại sao khi mà trong 1 số hệ điều hành đời cổ, (các bạn lính mới bây giờ chắc không gặp) nhiều bạn thử giải phóng bộ nhớ rồi, delete rồi, free rồi mà khi in thử ra vẫn thấy kết quả như thế .
đơn giản thôi, a ta trả lại mảnh đất đó, nhưng chưa có ai thuê nó cả, chưa có ai sử dụng nên hôm sau ra xem thử thì nó vẫn như hôm trước khi a ta trả lại
Các bạn đọc rõ chú ý ở dưới rồi hẵng hỏi thêm về câu này nhé.
Và các bạn phải chú ý là quyền sử dụng đất mới là cái được quan tâm duy nhất của vấn đề này
PHP Code:
int *a=new int[10];int *b=(int*)malloc(1000);
tiếp theo
PHP Code:
free(b);delete []a;
<<< điều này giải thích cho cách hiểu sai lầm của 1 số bạn mới học đối với việc cấp phát và giải phóng
4. Memory leak
Câu hỏi mở rộng :
như thế này có phải là giải phóng ko
PHP Code:
int*x=new int[20];
x=NULL; <<<<< như thế này có phải là giải phóng ko
câu trả lời là không , bạn đã hiểu sai lầm hoàn toàn về việc giải phóng rồi, bạn nên đọc kĩ lại phần giải phóng để hiểu tại sao.
như thế này chính là :
anh ta đánh mất cái quyền sử dụng đất của mình, kết quả là vùng đất đó ko được sở lấy về, sau nhiều lần như thế thì tài nguyên đất của sở càng ngày càng ít đi, hiện tượng này gọi mà memory leak
Sau khi chương trình kết thúc , việc bộ nhớ xin cấp phát có được tự giải phóng hay ko thì tùy thuộc vào cài đặt của trình biên dịch và hệ điều hành. Chúng ta có 2 khả năng · Khả năng 1 : trong phần khởi động (trước khi vào function main() ), program xin một khối memory cuả system gọi là XXXX và mỗi lần malloc được gọi thì cấp pháp một phần memory cuả XXXX cho malloc. Do đó, khi program exit thì trả XXXX về cho system là xong. Trong trường hợp này không bị mất memory
· Khả năng 2 : mỗi lần malloc được gọi thì xin memory từ system . Trường hợp này có thể memory không trả về cho system. Lúc này chương trình sẽ bị gọi là có memory leak.Như vậy sau vài lần chạy sẽ ko còn memory để cấp phát nữa
Đó là giải thích tại sao có nhiều chương trình chạy xong, thoát ra rồi, f5 mấy lần rồi mà máy vẫn cứ ì ì ì ra..........
5. Trên đây là cách lý thuyết cơ bản dành cho các bạn mới học, nó được áp dụng đối với lập trình trên console, (cấp sở tài nguyên thôi)
trong windows nó cũng như thế thôi nhưng mà nó có thêm nhiều quy tắc rằng buộc chặt chẽ hơn rất nhiều (cấp bộ tài nguyên và môi trường, phải khác chứ)
Muốn biết thêm về bộ nhớ thì xem chap 1 của tut dưới đây :
Portable Executable File Format
Update 9/9/10
Câu hỏi
Nhân tiện cho em hỏi, nếu mình khai báo 1 mảng có thể có rất nhiều phần tử thì bộ nhớ của nó sẽ được lấy từ đâu ra (Ổ cứng, Ram.... Hay là một cái gì đó mà em không biết :P). Khi em khai báo 1 mảng int a[1000000] thì nó báo là "Array size too large". Mới có 1000000 phần tử nó đã coi là lớn thì những bài toán thực tế vài triệu phần tử liền thì phải làm thế nào? hix
Trả lời
int a[1000000] ; khai báo ở đâu ?
em khai báo ở sở (tức là khai báo dạng local, trong các hàm )thì sở nó xin vùng nhớ ở stack segment, mà stack segment thì đây (trong ảnh, nhỏ gọn thế này, liệu nó có cho em vùng lớn thế kia ko 1000000*4byte)
Click vào ảnh để xem hình đẩy đủ
đối với các bài toán cần nhiều vùng nhớ 1 cách kinh khủng thì ta thường dùng các hàm api về malloc để lấy các vùng nhớ ở free store được bộ (os-hệ điều hành) cấp phát,
và 1 điều ko kém phần quan trọng đó là ta nên xây dựng những giải thuật thật thông minh chứ ko phải là load tràn hết lên bộ nhớ
ví dụ xây dựng trước các phương pháp xử lý các sự kiện có thể xảy ra
giả sử như này, tôi có 1 khối thông tin, để bắt sự kiện "tìm nhân viên mới vào công ti", tôi lập ra 1 temponary, mỗi khi chèn thằng mới vào khối thông tin của tôi, tôi gán thằng temponary này bằng với nhân viên mới, như thế tôi đã có 1 phương pháp sử lí sự kiện tốt rồi đúng ko ???
Update 10/9/10
câu hỏi
Cấp phát động thì nó lấy bộ nhớ từ đâu vậy cà.
"data segment"
Là cái gì thế em dịch là dữ liệu phân đoạn, nghĩa là sao đây, anh langman bận rộn thế :P:P
a. theo giáo trình đại học FPT về OS,theo giáo trình thầy phạm văn ất về tổ thức bộ nhớ, khi tiến trình chạy , bộ nhớ được mô hình thành 4 phần như sau
(trên thực tế, trong windows, môi trường ảo hóa cụ thể này thì có cách tổ chức phức tạp hơn phát triển từ lý thuyết này)
b. đang bận ôn thi ko có time online được
Update 20/11/10
Câu hỏi của quyết 1991 : sự khác nhau giữa malloc và new?
new và malloc khác nhau cực cực kì nhiều đó các pạn à
sơ bộ như sau, chưa phân tích kĩ
malloc là hàm, cấp phát trả về kiểu void *, malloc thì ko gọi hàm tạo
free ko gọi hàm hủy
malloc trả về NULL nếu thất bại
new là toán tử, new gọi hàm tạo, new có thể được đa năng hóa (nạp chồng),
new ném ra exception nếu thất bại
toán tử new và toán tử new[] ko có khả năng realloc
Update tiếp câu hỏi hay 2/3/2010
xin khẳng định lại 1 lần nữa, e đã hiểu hoàn toàn sai lầm, FREE và DEL ko bao giờ thay đổi giá trị của con trỏ, hãy phân việt rõ ràng giữa giá trị của con trỏ và giá trị nó trỏ đến
free nó là void free(void *mem) vậy thì xin hỏi con trỏ mem làm sao có thể thay đổi giá trị qua hàm này (xin hãy đọc bài bản chất con trỏ trong C để hiểu sâu hơn vấn đề này, tip : phân biệt rõ ràng giữa giá trị của mem và giá trị của thằng mà mem trỏ tới)
check lại đoạn code sau đây
C++ Code:
- #include <iostream>
- using namespace std;
- int main(){
- int *p;
- p= new int[2]; // xin chính quyền cấp hai khu đất
- p[0]=8888; // khu này trồng rau
- p[1]=9999; // khu này nuôi lợn
- printf("%x\n",p); // giá trị của p <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- delete [] p; // trả lại đất cho chính quyền
- printf("%x\n",p); // giá trị của p <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
- system("pause");
- return 0;
- }
điều nữa
Giải bộ nhớ hoạt động như thế nào : bản chất là trả lại quyền sử dụng
khi này :
+ sở sẽ thu lại quyền sử dụng đất của anh, thế là đủ rồi, sở ko cần phải động chạm sửa chữa lại gì vùng đất đó. Nên khi đó dù vùng đất đó đã được giải phóng nhưng mà hoa màu của a ta trên đó thì vẫn còn, ko có biến mất được
điều này giải thích tại sao khi mà nhiều bạn thử giải phóng bộ nhớ rồi, delete rồi, free rồi mà khi in thử ra vẫn thấy kết quả như thế .
đơn giản thôi, a ta trả lại mảnh đất đó, nhưng chưa có ai thuê nó cả, chưa có ai sử dụng nên hôm sau ra xem thử thì nó vẫn như hôm trước khi a ta trả lại
khi này :
+ sở sẽ thu lại quyền sử dụng đất của anh, thế là đủ rồi, sở ko cần phải động chạm sửa chữa lại gì vùng đất đó. Nên khi đó dù vùng đất đó đã được giải phóng nhưng mà hoa màu của a ta trên đó thì vẫn còn, ko có biến mất được
điều này giải thích tại sao khi mà nhiều bạn thử giải phóng bộ nhớ rồi, delete rồi, free rồi mà khi in thử ra vẫn thấy kết quả như thế .
đơn giản thôi, a ta trả lại mảnh đất đó, nhưng chưa có ai thuê nó cả, chưa có ai sử dụng nên hôm sau ra xem thử thì nó vẫn như hôm trước khi a ta trả lại
(windows có bao nhiêu process, thread,? nên việc bị thuê ngay lập tức là quá bình thường, em à, đặc biệt nếu là hàng nằm trên stack thì thay đổi liên tục là bt)
More :
khi em cài hook bắt các API trên window sẽ thấy LocalAlloc, RemoteAlloc,GlobalAlloc... được xài rất nhiều lần trên /1s chứ ko phải (ví dụ nhỏ xem ở hình dưới , đó là chỉ trong 1 tiến trình firefox thôi đó, chứ ko phải xét trên 5x process đang chạy)
tuy nhiên đối với các môi trường cũ, đặc biệt như trên borland C for dos thì hiện tượng free rồi mà còn tài nguyên rất hay xảy ra, có rât rất nhiều người hiểu lầm là lỗi, rồi ... (đã có rất nhiều câu hỏi như thế trong box thắc mắc C). đó là lý do vì sau a phải nhấn mạnh điều đó
Không có nhận xét nào:
Đăng nhận xét