Các bác có kinh nghiệm lcao thủ ập trình trong eVC post vài bài về quản lý bộ nhớ giúp anh em mới vào nghề cái.
Em có một vấn đề sau về bộ nhớ
Em cần một mảng CPoint diem[500][10]
Nếu em khai theo kiểu mảng động:
trong header: CPoint **diem;
trong ctrình cấp phát dần :
diem=new CPoint *; // i<500
diem[k]=new CPoint[10];
thì khi cho i tầm 30-40 thì chương trình báo lỗi .
Nếu em khai ngay từ đầu CPoint diem[500][10] thì lại không có lỗi.
Theo ý kiến chủ quan nếu cấp phát động thì tốt hơn và tiết kiệm hơn, tại sao lại lỗi hả các bác???
Cấp phát dần là sao bác?
Nếu muốn dùng mạng động kích thước [500][10] thì mình có thể làm như sau:
[CODE]
int n = 500, m = 10;
CPoint diem;
diem = new CPoint[n];
int i, j;
for (i=0; i<n; i++){
diem = new CPoint[m];
}
for (i=0; i<n; i++){
for (j=0; j<m; j++){
CPoint p;
p.x = i;
p.y = j;
diem *[j] = p;
CString s;
s.Format(TEXT("%d, %d"), diem*[j].x, diem*[j].y);
this->SetWindowText(s);
}
}
for (i=0; i<n; i++){
delete diem*;
}
delete diem;[/CODE]
Bạn nhớ giải phóng bộ nhớ sau khi dùng! Quên giải phóng bộ nhớ là 1 lỗi cơ bản mà nhiều người mắc phải.******
May quá có người quan tâm giúp rồi.
Xóa bộ nhớ sao lại phải xóa 2 lần như thế ạ, em tưởng delete diem là đựoc chứ ạ, cần cả vòng lặp để xóa như thế kia nữa hả bác??
Cấp phát dần có nghĩa là biến n, và trong a[n][m] trong từng trường hợp là khác nhau ( nhưng đều <500). Em mới nghĩ cấp phát dần là cách làm để tiết kiệm bộ nhớ nhất.
Bác cho em hỏi, cách của bác với cách khai thẳng
int ARR[500][10] là không khác nhau đúng không ?
khai báo ngay từ đầu int ARR[500][10] trong eVC là nó cấp phát bộ nhớ luôn đúng không ạ ?
Sao trong một số trường hợp khai báo như kiểu của bác, dùng xong delete đi thì lỗi thiếu bộ nhớ, trong khi khai báo ngay từ đầu kiểu int ARR[500][10] lại không lỗi bộ nhớ?
Có cách nào để biết được các thông số về bộ nhớ, quản lý bộ nhớ của chương trình mình làm không các bác
Xin chân thành cảm ơn .
Hì vấn đề bộ nhớ có khá nhiều cái hay, mình rất khoái các vấn đề liên quan đến hệ thống, nhưng do chưa thể dùng nó để kiếm sống được nên đã quẳng vào kho hơi lâu. Hôm nay có bác Tư Triều vào lục lại giùm thì cảm ơn nhiều quá. Những điều mình nói ở đây mang tính chất bàn luận, bác nào thấy sai thì sửa giúp.
hix, tèo rồi, cấp phát phải dùng vòng for thì xoá cũng phải dùng vòng for chứ
Nếu bạn khai báo **diem nghĩa là sao? Bạn hình dung được ko?
- Nếu ban khai báo CPoint diem[n][m] có nghĩa là bạn đã cấp phát tính 1 khối bộ nhớ mà mình thường gọi là 1 ma trận có kích thước n x m. Nhưng thực tế không phải vậy, thực tế thì khối bộ nhớ này là liên tiếp nhau, mình hoàn toàn có thể dùng 1 vòng for để tra cứu, thay đổi vùng nhớ này (không cần dùng 2 vòng for như ta vẫn thường dùng).
- Còn nếu bạn khai báo CPoint **diem tức là mình muốn có 1 khối nhớ chưa biết trước kích thước. Khi nào mình cần dùng bao nhiêu thì sẽ xin bấy nhiêu. Tại sao phải làm vậy, mục đích chính chẳng qua là để tận dụng không gian nhớ. Chắc bạn đã nghe tới chuyện phân mảnh bộ nhớ chứ? Tại sao, nếu bạn đã học về Hệ điều hành thì chắc biết rằng sẽ có trường hợp là bộ nhớ còn dư rất nhiều nhưng khi mình xin cấp phát 1 miếng thì OS lại báo là “hết bộ nhớ rồi bác à”, đó là trường hợp phân mảnh bộ nhớ. Vấn đề này mình tạm dừng ở đây vì nói ra sẽ rất dài dòng, đụng tới quản lý tài nguyên của OS mà, nếu bạn có nhã hứng thì mình chờ ý kiến của bạn để tiếp tục câu chuyện. Quay lại vấn đề chính: bạn đã bao giờ có nhu cầu cần 1 mảng mà mảng đó có dạng m x nj ko? Có nghĩa là mình cần 1 mảng mà có m hàng, mỗi hàng bây giờ không còn là n cột nữa, mà hàng 1 có 4 cột, hàng 2 có 10 cột, hàng 3 có 6 cột, … hì, tạm dừng vấn đề nhé. Tiếp tục quay lại vấn đề, bạn hỏi là tại sao phải cùng vòng for để xoá: thế bạn khai báo CPoint **diem nghĩa là sao? Nghĩa là con trỏ của con trỏ, đúng ko? Mà con trỏ thì phải dùng delete, thế con trỏ của con trỏ thì phải dùng 2 lần delete chứ sao. Tóm lại bạn có thể hình dung là mảng các con trỏ thì phải dùng vòng for để del, đúng ko?
Như vậy, mỗi lần cấp phát lại bạn phải del cái cũ đi rồi cấp phát cái mới hoặc bản phải dùng các hàm hỗ trợ.
Sao bạn lại hỏi thế này nhỉ? Bạn đọc phần trả lời trên cùng của mình chắc sẽ hình dung ra. Câu trả lời là khác rất xa nhau. Đặc biệt sẽ thể hiện rõ khi bạn cần 1 mảng kích thích lớn, chẳng hạn: 9999999 x 9999999. Ai mà cũng khai báo dạng CPoint diem[9999999][9999999] thì chắc là sẽ khổ bác Bill lắm đây.
Đúng. (Nhưng đừng ạ, mình ngại lắm, mình còn ít tuổi lắm )
Hì bởi vì bạn dùng chưa đúng, bạn del có 1 lần thôi chứ gì?
VC ở chế độ debug thông báo rất rõ, hoặc mình có thể làm các test case.
Không có chi, khách sáo quá, trao đổi học hỏi kinh nghiệm là chính thôi mà
Okie, đêm qua em đã khắc phục được rồi.
More Q :
- Về nguyên tắc đâu đó trong PC thì bộ nhớ sử dụng có thể lên được 4G
nhưng trong PDA bác có biết maxxi là ?? - Nếu khai báo kiểu *int a rồi sau đó dùng luôn a[1]=10 chẳng hạn thì trong một số trường hợp không lỗi, bác có thể phân tích cụ thể hơn chuyện này không.Cụ thể ở mức hệ điều hành làm gì thì tốt.
Xin chân thành cảm ơn.
Nhỏ lớn khôgn quan trọng, biết hơn thì vẫn truyền thụ được như thường.
dwProcessorType
The following list shows the possible values for this member:
PROCESSOR_INTEL_386
PROCESSOR_INTEL_486
PROCESSOR_INTEL_PENTIUM
PROCESSOR_INTEL_PENTIUMII
PROCESSOR_MIPS_R4000
PROCESSOR_HITACHI_SH3
PROCESSOR_HITACHI_SH4
PROCESSOR_STRONGARM
PROCESSOR_ARM720
PROCESSOR_MIPS_R5000
PROCESSOR_SHx_SH3DSP
Nhìn những dòng trên bạn thấy WM hỗ trợ cả CPU intel 386, tức là có tới 32 bit địa chỉ, cũng có nghĩa là - về mặt lý thuyết - nó sẽ hỗ trợ được tối đa 4GB mem như Windows trên PC.
Hì dùng thế này có lúc được lúc không có nghĩa là, lúc được là do chẳng may, còn lúc không được mới là đúng.
Khi bạn khai int *a thì bạn đã được 1 con trỏ, trỏ đến 1 vùng nhớ bất kỳ không được xác định. Do đó khi bạn gán a[1] = 10, thì ô nhớ đầu tiên được gán bằng 10. Không gây ra lỗi đó là do đoạn mã khác chưa dùng tới ô nhớ đó. Bạn chạy chương trình 1 lúc thế nào cũng sinh lỗi Bạn phải cấp phát bộ nhớ thì ô nhớ mình dùng tới sẽ được đánh dấu là “đang dùng”, khi đó đoạn mã khác mới ko xâm phạm vào và ko sinh lỗi.
khà khà, cảm ơn nhiều nhé.Okie về bộ nhớ rồi.