Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 11 kết quả

Đề tài: Lập trình C | Cấp phát động trong lập trình C

  1. #1
    Ngày gia nhập
    08 2006
    Bài viết
    19

    Talking Lập trình C | Cấp phát động trong lập trình C

    tôi vừa gõ thử cái này để kiểm tra cấp phát bộ nhớ cho xâu kí tự

    C Code:
    1. #include<stdio.h>
    2. #include<conio.h>
    3. #include<string.h>
    4. #include<stdlib.h>
    5. void main()
    6. {
    7.  char *s=NULL;
    8.  int i;
    9.  clrscr();
    10.  s=(char *) malloc(5*sizeof(char));
    11.  printf("nhap vao 1 xau bat ki:\n");
    12.  gets(s);
    13.  printf("kich thuoc %d\n",sizeof(s));
    14.  printf("%s\n",s);
    15.  for (i=0;i<strlen(s);i++) printf("%c",*(s+i)); // cai nay cho vao de test thu
    16.  getch();
    17. }

    chương trình chỉ cấp phát cho s có 5 byte (hàm malloc)
    nhưng khi nhập vào xâu lớn(vd: hello every body), có tới 15 kí tự , nếu tính cả \0 thì là 16, vậy mà s vẫn nhận đầy đủ, lệnh sizeof(s) chỉ trả ra 4 byte
    có bác nào có thể giải thích giùm tôi được không

  2. #2
    Ngày gia nhập
    07 2006
    Bài viết
    121

    C là vậy đó cậu do đó người ta thường nói lập trình C là dành cho người lớn hiểu mình đang làm gì: Cậu xin 5 nhưng cậu vẫn có thể sài 8 nhưng hậu quả là do cậu gánh chịu.

  3. #3
    Ngày gia nhập
    09 2006
    Bài viết
    711

    s được khai báo là 1 pointer, nên sizeof(s) = sizeof(pointer), = 4 trên 32bit, 2 trên 16bit, 8 trên 64bit.
    gets với content lớn hơn kích thước cấp cho s sẽ gây lỗi nghiêm trọng, thường là Heap corrupt, và app thường sẽ bị crash.

  4. #4
    Ngày gia nhập
    08 2006
    Bài viết
    19

    ô nhớ cấp cho biến động nằm ngay trong bộ nhớ của chương trình, ở trên khi s dùng vượt quá số ô nhớ được cấp phát nó sẽ tràn ra các ô nhớ đằng sau, gấy sai cho các biến khác có ô nhớ cấp phát ngay sau nó. Vấn đề là quái ở chỗ nếu chương trình trên tôi sửa một chút:
    char *s=NULL,*s1=NULL;
    s=(char *) malloc(5*sizeof(char));
    s1=(char *) malloc(10*sizeof(char));
    đánh liên tiếp 2 lệnh malloc tôi nghĩ s và s1 sẽ được cấp phát các ô nhớ liền nhau. vậy nếu dùng lệnh
    strcpy(s,"hello every body");
    strcpy(s1,"oh yes! very good");
    hoặc dùng 2 lệnh gets liên tiếp để nhập s, s1 vào
    thì đáng lẽ khi in 2 biến này ra, s1 sẽ sai !
    thực tế tôi chạy chương trình:
    nếu dùng 2 lệnh strcpy() hoặc 2 lệnh gets() thì s, s1 in ra đều đúng !
    nếu dùng 1 lệnh strcpy() và 1 lệnh gets() thì chỉ s in sai phần cuối của xâu, s1 in ra vẫn đúng. số kí tự in đúng của xâu s luôn là 10 kí tự(đấy là tôi nhập vào s xâu 20 kí tự)

  5. #5
    Ngày gia nhập
    08 2006
    Bài viết
    59

    tôi nghĩ s và s1 sẽ được cấp phát các ô nhớ liền nhau
    => bạn nên kiểm chứng lại điều này (chưa chắc là đúng đâu): in ra 2 con trỏ hoặc in ra hiệu số giá trị của 2 con trỏ

    -thân

  6. #6
    Ngày gia nhập
    09 2006
    Bài viết
    711

    Mặc định Lập trình C | Cấp phát động trong lập trình C

    Hoàn toàn không có gì chắc chắn và 99,9% sai khi nói s và s1 sẽ được cấp hai vùng nhớ liền kề nhau. Cơ chế cấp phát bộ nhớ của C RTL, Windows, OS cực kỳ phức tạp, cấp phát ra sao thì cũng gần như không thể biết được.
    Vd với VC sau nay, cáccác hàm new, malloc đều là wrapper của HeapAlloc, vậy HeapAlloc làm việc ra sao, chúng ta phải RE xuống NtHeapAlloc, NtVirtualAlloc, rồi xuống kernel, thậm chí xuống tới CPU với cơ chế virtual memory để tìm hiểu. Gần như không thể !!!;(
    Xin cái gì thì dùng cái đó, đừng thắc mắc hay thử để chết cái đùng.

  7. #7
    Ngày gia nhập
    08 2006
    Nơi ở
    TpHCM
    Bài viết
    202

    Hoàn toàn không có gì chắc chắn và 99,9% sai khi nói s và s1 sẽ được cấp hai vùng nhớ liền kề nhau
    đồng ý

    trở lại với cái post đầu tiên

    vì khai báo là char* s, nên sizeof(s) lúc nào cũng return =4, cho dù bạn có cấp phát đến ngàn vạn byte cũng thế thôi, vì s ở đây là con trỏ và thực chất con trỏ chỉ có 4 byte giống như int, giống như giải thích dưới đây
    Trích dẫn Nguyên bản được gửi bởi TQN
    s được khai báo là 1 pointer, nên sizeof(s) = sizeof(pointer), = 4 trên 32bit, 2 trên 16bit, 8 trên 64bit.
    gets với content lớn hơn kích thước cấp cho s sẽ gây lỗi nghiêm trọng, thường là Heap corrupt, và app thường sẽ bị crash.
    nếu khai báo char s[1024], thì sizeof(s) sẽ = 1024, nó không phụ thuộc vào
    gets(s) bạn sẽ nhập vào bao nhiêu kí tự, muốn biết đã nhập bao nhiêu thì phải dùng strlen(s) chứ không phải là sizeof

  8. #8
    Ngày gia nhập
    11 2006
    Bài viết
    3

    Bác chỉ được cái nói đúng, khai báo biến kiểu gì thì nó trả về chính xác cấu trúc của kiểu dữ liệu đó vì nó là con trỏ.
    Còn hàm gets theo như mình biết thì nó sẽ lấy tất cả các giá trị kể cả giá trị còn nằm trong vùng đệm, cái này cũng chính là điểm khác nhau của scanf và gets.

  9. #9
    Ngày gia nhập
    07 2006
    Nơi ở
    Hanoi, Vietnam
    Bài viết
    2,750

    Liên quan gì đến gets, và scanf nhỉ?

    Có Bro nào máy chỉ có nguyên cái DOS OS test thử xem sao?

    Đối với Windows cấp cho mỗi chương trình con win32 một vùng nhớ ảo được phân sẵn tới 4GB, một chương trình có thể định địa chỉ thoải mái trong 4GB này, chỉ cần tuân theo các Rules của Windows là được. Điều này đã giảm đi việc ghi đè dữ liệu hay code lên chương trình khác. Nhưng ở win32 các chương trình sẽ không còn nhìn thấy nhau thoải mái như ở win16.

    Win32 cũng chỉ còn có một kiểu bộ nhớ là "Flat memory model" (Kiểu bộ nhớ phẳng liên tục tới 4GB, mà không còn các kiểu bộ nhớ như Small, Tiny, Medium,Large, Huge ) và cũng không có kiểu 64KB cho mỗi segment nữa. Điều này cũng làm đơn giản cho lập trình viên nhiều.

    Như vậy phần nào đó ở Win32 cũng làm ảnh hưởng tới các hàm cấp phát bộ nhớ???? Chắc là phải tác giả trả lời có lẽ chính xác hơn nhỉ. Có gì sai, mọi người sửa và bổ sung giúp nhé.

    Dreaminess đi sinh nhật đây.
    Email: admin[@]congdongcviet.com | CC to: info[@]congdongcviet.com
    Phone: 0972 89 7667 (Office: 04 6329 2380)
    Yahoo & Skype: dreaminess_world (Vui lòng chỉ rõ mục đích ngay khi liên hệ, cảm ơn!)

    Một người nào đó coi thường ý thức kỷ luật cũng có nghĩa là người đó đã coi thường tương lai số phận của chính bản thân người đó. Những người coi thường ý thức kỷ luật sẽ không bao giờ có được sự thành công trong sự nghiệp!

  10. #10
    Ngày gia nhập
    08 2006
    Nơi ở
    Chương Mỹ-Hà Tây
    Bài viết
    27

    việc cấp phát đọng có thể dùng New dược không tôi thường dùng chúng
    đê cấp phát
    abc345

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn