2012-03-15 5 views
11

Mã dưới đây trả về một địa chỉ khi được thực hiện trong Windows, mặc dù tôi đã mong đợi nó trả về NULL.Tại sao malloc (0) trả về một địa chỉ không null trong Windows?

int main() 
{ 
    char *ptr = NULL; 
    ptr = malloc(0); 
    printf("malloc returned = %u\n", ptr); 

} 

Điều gì có thể đã thúc đẩy việc triển khai malloc như vậy? Có lý do gì đằng sau nó không?

Vì đây là bộ nhớ 0 byte nên tôi không thử viết bất kỳ dữ liệu nào. Nhưng, bộ nhớ này có thể được sử dụng cho bất cứ điều gì cả?

Trả lời

9

Nó chỉ có kích thước tối thiểu mà bạn đang yêu cầu. Và vì không có khối zero-length trong đống Win32, bạn có thể:

void *p = malloc(0); 
// ... do some stuff in between... 
realloc(p, n); 

Mà chủ yếu nên kết quả trong tái sử dụng một khối đống (nếu bạn may mắn và kích thước mới là nhỏ). Một tối ưu hóa cơ hội nhỏ (hoặc chậm lại, tùy thuộc vào bối cảnh và mức độ cà phê trong máu).

Đây là ví dụ đơn giản. Tình hình thực tế có thể là một lớp phân bổ bộ đệm khi nó được tạo và cũng cho phép phát triển nó. Nếu các yếu tố đầu vào gây phiền nhiễu để kiểm soát, bạn có thể chỉ để cho nó thực hiện việc phân bổ bộ đệm có kích thước bằng không.

+0

+1 như tôi đã thực sự nhìn thấy 1 người sử dụng này để "lợi thế" của mình khi ông không muốn trường hợp đặc biệt bất cứ điều gì trong một vòng lặp mà có thể phát triển bộ nhớ malloc'd/realloc'd rất lớn. – JimR

+1

Mặc dù vậy, bạn có thể chuyển một con trỏ rỗng vào 'realloc', vì vậy mẹo này không cần thiết. Bạn cũng có thể 'void * p = 0;'. –

+0

@Steve Nó không thực sự là một thủ thuật. Đó là một tạo phẩm của lập trình và thông số kỹ thuật nền tảng rời. Nếu không có thử nghiệm, nó không phải là rõ ràng như thế nào HeapRealloc (heap, HEAP_REALLOC_IN_PLACE_ONLY, 0, 4) sẽ hành xử, ví dụ. – ActiveTrayPrntrTagDataStrDrvr

7

Đó là trả lời trong comp.lang.c FAQ: http://c-faq.com/ansi/malloc0.html

Các ANSI/ISO tiêu chuẩn nói rằng nó có thể làm một trong hai; hành vi được xác định thực hiện (xem câu hỏi 11.33). Mã di động phải cẩn thận không gọi malloc (0), hoặc được chuẩn bị cho khả năng trả về null.

+0

Nhưng, điều gì sẽ thực hiện triển khai chọn trả về một số giá trị hợp lệ? Nó không có ý nghĩa để trả về NULL trong mọi trường hợp? – Jay

+3

Không nhất thiết. Tôi rùng mình đến các nhà biên dịch trình biên dịch thứ hai, nhưng một người triển khai có thể muốn malloc trả về 'null' chỉ khi bộ nhớ có thể không thực sự được cấp phát. – CAbbott

+1

@Jay: vì việc triển khai hoàn toàn miễn phí, bạn cũng có thể quyết định làm bất kỳ mã nào ít hơn. Đó là hợp lý để quyết định không gặp rắc rối chính mình để viết thêm một dòng mã để kiểm tra đầu vào cho 0 và trả về một con trỏ null. Sau đó, một lần nữa, nếu việc thực hiện đã có một thử nghiệm mà kích thước yêu cầu không phải là vô lý lớn (và sẽ trả về một con trỏ null nếu nó là), thì nó có thể dễ dàng kiểm tra vô lý-lớn-hay-zero. –

8

Để trả lời phần thứ hai của câu hỏi của bạn không, bộ nhớ không thể được sử dụng cho bất cứ điều gì, vì "phần có thể truy cập của nó" là 0 byte bắt đầu từ địa chỉ trả về.

IIRC được đảm bảo rằng nếu việc triển khai không trả về không rỗng, thì đó sẽ là một địa chỉ khác nhau từ bất kỳ khối bộ nhớ hiện được phân bổ nào khác. Vì vậy, về lý thuyết bạn có thể sử dụng địa chỉ như một ID duy nhất tạm thời (của kiểu con trỏ), mặc dù rõ ràng có rất nhiều cách khác để nhận được một ID duy nhất. Và ngay cả khi bạn định sử dụng nó cho điều đó, malloc(1) sẽ hoạt động cũng như malloc(0) và dễ di chuyển hơn.

0

KHÔNG PHẢI là vô dụng. Các khối được trả về từ malloc được mong đợi là duy nhất. Vì vậy, mỗi khối được trả về bởi malloc mang cả hai dữ liệu trong khối và một định danh duy nhất cho nó, là địa chỉ của nó. Nếu thuộc tính sau là quan trọng, và thực tế là nó không chứa dữ liệu không phải là một vấn đề, thì nó rất hữu ích.

Tuy nhiên, như đã đề cập một cách tuyệt vời để viết mã không di động. Tuy nhiên, điều này không giống như mã bất hợp pháp, và nó hoàn toàn hợp lệ để thực hiện để hỗ trợ nó (như các cửa sổ hiển nhiên).