2010-03-19 34 views
9

Tôi là người mới bắt đầu trong C. Trong khi đọc mã nguồn của git, tôi đã tìm thấy hàm bao bọc này quanh malloc.Wrapping malloc - C

void *xmalloc(size_t size) 
{ 
    void *ret = malloc(size); 
    if (!ret && !size) 
     ret = malloc(1); 
    if (!ret) { 
     release_pack_memory(size, -1); 
     ret = malloc(size); 
     if (!ret && !size) 
      ret = malloc(1); 
     if (!ret) 
      die("Out of memory, malloc failed"); 
    } 
#ifdef XMALLOC_POISON 
    memset(ret, 0xA5, size); 
#endif 
    return ret; 
} 

Câu hỏi

  1. Tôi không thể hiểu tại sao họ sử dụng malloc(1)?
  2. release_pack_memory làm gì và tôi không thể tìm thấy triển khai chức năng này trong toàn bộ mã nguồn.
  3. #ifdef XMALLOC_POISON memset(ret, 0xA5, size); là gì?

Tôi đang lên kế hoạch sử dụng lại chức năng này trong dự án của mình. Đây có phải là trình bao bọc tốt khoảng malloc không?

Mọi trợ giúp đều tuyệt vời.

+7

Kudo để đọc mã của các chương trình phức tạp hiện có - Tôi muốn nhiều nhà phát triển hơn đã làm điều đó. – Lars

+3

Đối với câu hỏi 2: Định nghĩa của nó là trong sha1_file.c (nó cho bộ nhớ để làm với các đối tượng gói của git, có lẽ) và nguyên mẫu của nó là trong git-compat-util.h. (Gợi ý: miễn là bạn đang tìm kiếm mã nguồn của git, hãy sử dụng 'git grep release_pack_memory' để tìm nó!) – Cascabel

+1

@Lars: Cảm ơn. @ Jefromi: Điểm tốt về 'git grep'. –

Trả lời

3
  1. malloc (0) không hoạt động trên tất cả nền tảng, trong trường hợp đó, phân bổ một byte được thực hiện thay thế. Việc cho phép phân bổ khối bộ nhớ 0-độ dài đơn giản hóa logic cấp cao hơn của chương trình.

  2. Không biết.

  3. Bằng cách lấp đầy bộ nhớ được cấp phát với giá trị khác 0, bạn sẽ dễ dàng tìm thấy lỗi trong chương trình mà bộ nhớ được sử dụng mà không khởi tạo thích hợp: chương trình sẽ sụp đổ gần như ngay lập tức trong các trường hợp như vậy. Khi lấp đầy bộ nhớ cần có thời gian, nó được bọc trong một bộ tiền xử lý xác định, vì vậy nó được biên dịch chỉ khi nào bạn muốn.

+1

Hành vi của 'malloc (0)' được thực hiện xác định. Nó hoặc là trả về một con trỏ NULL hoặc một con trỏ không null để không byte dữ liệu (mà, tất nhiên, bạn không bao giờ có thể dereference). C99 §7.20.3 Chức năng quản lý bộ nhớ: "Nếu kích thước của không gian được yêu cầu bằng 0, hành vi được thực hiện được xác định: hoặc con trỏ rỗng được trả về hoặc hành vi như thể kích thước là một số giá trị không phải là , ngoại trừ con trỏ trả về sẽ không được sử dụng để truy cập một đối tượng. " –

2

Đối với câu hỏi 1:

Tiêu chuẩn không xác định hành vi của malloc(0). Điều đó có thể trả lại một con trỏ hợp lệ hoặc nó có thể trả về NULL. Các cách triển khai khác nhau xử lý khác nhau để mã trở lại malloc(1) để có được hành vi nhất quán.

Đối với câu hỏi 3:

Nó đặt nội dung của bộ đệm thành nội dung 'lạ'. Bằng cách này, mã của bạn hy vọng không dựa vào nội dung là một cái gì đó cụ thể (mà malloc không đảm bảo).

+0

Bạn có đề xuất sử dụng trình bao bọc này không? –

+0

@Appu - thay đổi từ 0 đến 1 và thực hiện việc ghi nhớ là tốt. Cái chết trên chính sách OOM phụ thuộc vào những gì bạn đang viết. Chính sách này là tốt cho một tiện ích dòng lệnh thực hiện một điều và thoát. Chính sách có thể hoặc có thể không ổn cho một máy chủ tồn tại lâu dài (bạn có muốn thoát khỏi quá trình này hoặc bạn có muốn dọn dẹp yêu cầu hiện tại và thử lại). Chính sách này không được chấp nhận cho một thư viện chung vì chính sách về OOM nên được quyết định bởi ứng dụng chính. –

+0

Điểm tốt. Mã mà tôi sẽ viết là thư viện. Vì vậy, tôi nghĩ tôi nên tránh 'chết'. –

2

Đối với câu hỏi 2: release_pack_memory được tìm thấy trong sha1_file.c:570.

1

Tôi không quen thuộc với wrapper này nhưng đây là những gì nó làm

1 - nếu size = 0 đã được chỉ định sau đó nó phân bổ 1 byte thay vì nếu malloc cơ bản đã không làm như vậy

đây là lẽ làm như vậy mà một người gọi vẫn có thể làm miễn phí trên đó (như realloc)

2 tôi giả của nó để cố gắng ép buộc hệ thống bộ nhớ nằm bên dưới để xem xét kỹ hơn cho bộ nhớ

3 lực lượng XMALLOC_POISON để đệm cho một nhà nước biết đây là thực tiễn phổ biến để ngăn chặn và phát hiện các lỗi lạ do dữ liệu chưa được khởi tạo

Thứ hai - tại sao bạn muốn gói malloc. Bắt đầu với ý tưởng về những gì bạn muốn làm và sau đó thực hiện nó hoặc sao chép thực hiện. Lý do gói malloc

  1. phát hiện rò rỉ
  2. phân tích sử dụng
  3. bộ nhớ tổng hợp
  4. gỡ lỗi (như XMALLOC_POISON)
  5. thi kiểm tra

Hầu hết trong số này có thể được thực hiện với valgrind - mà làm nhiều hơn nữa.

'viết mã rắn' sách có bộ bao gồm bộ nhớ tốt cho 1,4 và 5

+0

Cảm ơn câu trả lời. Thành thật mà nói, tôi hơi lạc trong thế giới C. Vì vậy, để tránh tôi làm những sai lầm, tôi đang đọc mã chương trình khác và tìm hiểu cách họ viết mã. –

+2

"điều này có lẽ được thực hiện để người gọi vẫn có thể thực hiện được miễn phí" - bạn vẫn có thể gọi miễn phí hoặc realloc trên một con trỏ null. Tôi không biết nguồn của git, nhưng nhiều khả năng nó được thực hiện để đảm bảo rằng một 0 trở lại có thể được xử lý dứt khoát bởi người gọi như một lỗi, ngay cả khi đầu vào là 0. Hoặc có thể để đảm bảo rằng các con trỏ khác 0 phân bổ có kích thước so sánh khác nhau ("đây không phải là bộ đệm có kích thước bằng 0 của bạn, do đó không được là vali của bạn!"). –