2012-12-25 37 views
5

Tôi đang nghiên cứu chức năng malloc này và tôi có thể sử dụng một số giúp đỡ:Malloc và Void Pointers

static void *malloc(int size) 
    { 
     void *p; 

     if (size < 0) 
       error("Malloc error"); 
     if (!malloc_ptr) 
       malloc_ptr = free_mem_ptr; 

     malloc_ptr = (malloc_ptr + 3) & ~3;  /* Align */ 

     p = (void *)malloc_ptr; 
     malloc_ptr += size; 

     if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) 
       error("Out of memory"); 

     malloc_count++; 
     return p; 
} 

Tôi biết rằng malloc func giao đất không gian bộ nhớ cho bất kỳ loại, nếu có đủ bộ nhớ, nhưng các dòng tôi không hiểu là:

p = (void *)malloc_ptr; 
malloc_ptr += size; 

Làm cách nào nó có thể trỏ đến bất kỳ loại dữ liệu nào như vậy? Tôi chỉ không thể hiểu được con trỏ void đó hoặc vị trí của nó.

LƯU Ý: malloc_ptr là một unsigned long

+0

Mã này chứa các giả định rằng một con trỏ cho 'long' unsigned (tức là 'malloc_ptr') có thể cũng chỉ cho bất kỳ đối tượng nào khác, từ một điểm liên kết. Giả định này không phải lúc nào cũng đúng (ví dụ, trên một số hệ thống, nó có thể không có khả năng trỏ đến các đối tượng 'long double'). –

+0

Mã giả định rằng không có loại nào có yêu cầu căn chỉnh chặt chẽ hơn so với căn chỉnh 4 byte. Mã không hiển thị cách 'free_mem_ptr' và' free_mem_end_ptr' được khởi tạo. Nó không trả về NULL khi không còn chỗ trống. Nếu hàm 'error()' trả về, thì tất cả các địa ngục sẽ bị mất. –

Trả lời

5

Lý do nó trả về một con trỏ void là bởi vì nó không có ý tưởng những gì bạn đang phân bổ không gian cho trong malloc gọi. Tất cả nó biết là số lượng không gian bạn yêu cầu. Đó là vào bạn hoặc trình biên dịch của bạn để quyết định những gì sẽ lấp đầy bộ nhớ. Vị trí của con trỏ void thường được thực hiện như một danh sách liên kết để duy trì tính toàn vẹn và biết giá trị của bộ nhớ là gì miễn phí được theo dõi đáng kể trong hàm free.

+0

nhưng làm thế nào để nó biết bao nhiêu không gian để phân bổ? nó sử dụng giá trị kích thước như thế nào? Tôi chỉ không nhìn thấy nó. Ví dụ tôi có một cấu trúc với 8 ints 3 ký tự và 1 float, được gọi là mystruct, và trong lý thuyết nó nên phân bổ không gian bộ nhớ cho nhiều, nhưng tôi chỉ không thể hiểu làm thế nào – morcillo

+0

@morcillo Trong trường hợp đó bạn có thể sẽ sử dụng ' toán tử sizeof' sẽ xác định kích thước đúng theo byte cần thiết để phân bổ đúng cấu trúc mà bạn đã khai báo. – squiguy

+0

Tôi biết sizeof là cho điều đó, nhưng những gì tôi không hiểu là làm thế nào để phân bổ không gian trong bộ nhớ. malloc_ptr có kích thước của kiểu nhưng p = (void *) malloc_ptr biết phân bổ 8 byte hoặc 2 byte hoặc 152 byte như thế nào? là đúc đến chức năng malloc mà làm cho nó hoạt động? (my_struct *) malloc (sizeof (my_struct)) ?? – morcillo

1

Malloc đang trả về một con trỏ cho một đoạn bộ nhớ phẳng hoàn toàn không có cấu trúc. Con trỏ (void *) có nghĩa là nó không biết nó trỏ đến đâu (không có cấu trúc), chỉ đơn thuần là nó trỏ đến một số bộ nhớ có kích thước kích thước.

Bên ngoài cuộc gọi của bạn tới malloc, sau đó bạn có thể cho chương trình biết rằng con trỏ này có một số cấu trúc. Tức là, nếu bạn có cấu trúc some_struct, bạn có thể nói: .

Xem cách malloc chỉ biết kích thước của những gì nó sẽ phân bổ, nhưng thực sự không biết cấu trúc của nó? Cuộc gọi của bạn tới malloc không truyền thông tin về cấu trúc, chỉ đơn thuần là kích thước bộ nhớ phân bổ.

Đây là cách của C là chung chung: malloc trả về cho bạn một số lượng bộ nhớ nhất định và đó là công việc của bạn để truyền nó đến bộ nhớ có cấu trúc mà bạn cần.

1

Đây là triển khai của malloc, vì vậy, nó được phép làm những việc không hợp pháp trong chương trình thông thường. Cụ thể, nó đang tận dụng chuyển đổi được triển khai từ unsigned long đến void *. Bộ khởi tạo chương trình malloc_ptr đến địa chỉ số số của một khối lớn bộ nhớ chưa được phân bổ. Sau đó, khi bạn yêu cầu phân bổ, malloc tạo con trỏ ra khỏi giá trị hiện tại của malloc_ptr và tăng số malloc_ptr theo số byte bạn đã yêu cầu. Bằng cách đó, lần sau bạn gọi malloc nó sẽ trả về một con trỏ mới.

Đây là về việc triển khai đơn giản nhất có thể là malloc. Đáng chú ý nhất, nó xuất hiện không bao giờ tái sử dụng bộ nhớ giải phóng.

1
p = (void *)malloc_ptr; 

`malloc` returns a void pointer, which indicates that it is a pointer to a region of 
unknown data type. The use of casting is only required in C++ due to the strong type 
system, whereas this is not the case in C. The lack of a specific pointer type 
returned from `malloc` is `type-unsafe` behaviour according to some programmers: 
malloc allocates based on byte count but not on type. 

malloc_ptr += size; 

`C` implicitly casts from and to `void*`, so the cast will be done automatically. In 
`C++` only conversion to void* would be done implicitly, for the other direction an 
explicit cast is required. 

Wiki giải thích về loại đúc,

`malloc` function returns an untyped pointer type `void *`, which the calling code must 
cast to the appropriate pointer type. Older C specifications required an explicit cast 
to do so, therefore the code `(struct foo *) malloc(sizeof(struct foo))` became the 
accepted practice. However, this practice is discouraged in ANSI C as it can mask a 
failure to include the header file in which `malloc` is defined, resulting in 
downstream errors on machines where the int and pointer types are of different sizes, 
such as the now-ubiquitous x86_64 architecture. A conflict arises in code that is 
required to compile as C++, since the cast is necessary in that language. 
1

Như bạn thấy cả hai dòng này,

p = (void *)malloc_ptr; 
malloc_ptr += size; 

đây bạn đang gặp malloc_ptr kiểu unsigned dài vì vậy chúng tôi loại đúc biến này để vô hiệu hóa loại và sau đó lưu trữ nó trong p. và theo cách tương tự, thứ hai là ký hiệu malloc_ptr = malloc_ptr + size;

Và cả hai mã này đều dành cho nhà phát triển sự thoải mái vì p là loại con trỏ void vì vậy trong ứng dụng khi bạn sử dụng malloc thì bạn không biết loại khối bộ nhớ nào phải được trả về theo chức năng để chức năng này luôn trả về con trỏ void chung để chúng ta có thể định kiểu lại trong ứng dụng theo yêu cầu.

và cùng trong mã thứ hai nếu bạn là nhập kích thước trong tiêu cực thì điều gì xảy ra với tình trạng này

if (free_mem_end_ptr && malloc_ptr >= free_mem_end_ptr) 
error("Out of memory");