2010-09-10 31 views
11

realloc được sử dụng để phân bổ lại bộ nhớ động.Điều gì sẽ thực hiện nếu không có không gian tuần tự bộ nhớ?

Giả sử tôi đã cấp 7 byte sử dụng hàm malloc và bây giờ tôi muốn mở rộng nó thành 30 byte.

Điều gì sẽ xảy ra trong nền nếu không có không gian tuần tự (liên tục trong một hàng) 30 byte trong bộ nhớ?

Có lỗi hoặc bộ nhớ nào được phân bổ trong các phần không?

Trả lời

11

realloc công trình đằng sau hậu trường gần như thế này:

  • Nếu có đủ không gian trống phía sau khối hiện hành để thực hiện yêu cầu, mở rộng khối hiện tại và trả về một con trỏ đến đầu của khối .
  • Khác nếu có một khối đủ lớn miễn phí ở nơi khác, sau đó phân bổ khối đó, sao chép dữ liệu từ khối cũ qua, giải phóng khối cũ và trả về con trỏ đến đầu khối mới
  • Báo cáo lỗi khác trở về NULL.

Vì vậy, bạn có thể kiểm tra cho sự thất bại bằng cách kiểm tra cho NULL, nhưng lưu ý rằng bạn không ghi đè lên con trỏ cũ quá sớm:

int* p = malloc(x); 
/* ... */ 
p = realloc(p, y); /* WRONG: Old pointer lost if realloc fails: memory leak! */ 
/* Correct way: */ 
{ 
    int* temp = realloc(p, y); 
    if (NULL == temp) 
    { 
    /* Handle error; p is still valid */ 
    } 
    else 
    { 
    /* p now possibly points to deallocated memory. Overwrite it with the pointer 
     to the new block, to start using that */ 
    p = temp; 
    } 
} 
+0

Đây có phải là 'realloc' hoạt động cho mọi triển khai không? –

+0

@CoolGuy: Một số triển khai có thể không (có thể) thực hiện bước đầu tiên của việc mở rộng khối hiện tại, nhưng nếu không thì đây là hành vi quan sát được của 'realloc' cho tất cả các triển khai. –

1

Từ man page:

realloc() trả về một con trỏ đến bộ nhớ vừa được cấp phát, đó là phù hợp thẳng hàng cho bất kỳ loại biến và có thể khác nhau từ ptr, hoặc NULL nếu yêu cầu không thành công.

Nói cách khác, để phát hiện lỗi, chỉ cần kiểm tra xem kết quả là NULL.

EDIT: Như đã lưu ý trong nhận xét, nếu cuộc gọi không thành công, bộ nhớ ban đầu sẽ không được giải phóng.

+2

Đáng giá để lưu ý từ trang người đàn ông: Nếu realloc() thất bại, khối gốc bị bỏ hoang; nó không được giải phóng hoặc di chuyển. –

6

realloc sẽ chỉ thành công nếu nó có thể trả về khối liên tiếp ("tuần tự" trong từ của bạn) khối bộ nhớ. Nếu không có khối như vậy tồn tại, nó sẽ trả về NULL.

+4

@Mark - bộ nhớ gốc không thay đổi. Một lỗi phổ biến trong ngữ cảnh này là 'x = realloc (x)' - bạn phải thực hiện 'newX = realloc (x)' để tránh rò rỉ lỗi x ban đầu. –

+0

@Steve Townsend - Thats chỉ khi nó thất bại? Khi thành công nó giải phóng con trỏ ban đầu. Và whos Đánh dấu trong trang này? O_o –

+0

Tôi đoán có lỗi. Nhận xét đầu tiên được hiển thị từ người dùng và bây giờ thay đổi của nó mặc dù cả hai đều được gửi đến Mark. Đó có phải là một lỗi không? :-P –

1

Nói chung, nó phụ thuộc vào việc triển khai. Trên x86 (-64) Linux, tôi tin rằng thuật toán malloc drench thường sẽ phân bổ tối thiểu một trang x86 chuẩn (4096 byte) cho kịch bản mà bạn mô tả ở trên, nó sẽ chỉ thiết lập lại các ranh giới để chứa thêm byte. Khi nói đến, hãy phân bổ lại bộ đệm từ 7byte thành PAGE_SIZE + 1 Tôi tin rằng nó sẽ cố gắng phân bổ trang kế tiếp tiếp theo nếu có.

Worth đọc những điều sau đây, nếu bạn đang phát triển trên Linux:

Theo mặc định, Linux sau một chiến lược phân bổ bộ nhớ lạc quan. Điều này có nghĩa là khi malloc() trả về non-NULL, không có gì đảm bảo rằng bộ nhớ thực sự có sẵn. Đây thực sự là lỗi lỗi . Trong trường hợp nó chỉ ra rằng hệ thống là hết bộ nhớ, một hoặc nhiều quá trình sẽ bị giết bởi kẻ giết người OOM khét tiếng. Trong trường hợp Linux được sử dụng trong những trường hợp mà nó sẽ là kém hấp dẫn đến bất ngờ mất một số quá trình chọn ngẫu nhiên, và hơn nữa phiên bản hạt nhân là đủ gần đây, người ta có thể tắt hành vi overcommitting này sử dụng một lệnh như:

# echo 2 > /proc/sys/vm/overcommit_memory 

Xem thêm thư mục Tài liệu hạt nhân, tệp vm/overcommit-accounting và sysctl/vm.txt.

0

FreeBSD và Mac OS X có reallocf() chức năng sẽ giải phóng con trỏ được truyền khi bộ nhớ được yêu cầu không thể được cấp phát (xem man realloc).

+0

Thay vì sử dụng điều này, nó sẽ có ý nghĩa hơn rất nhiều để chỉ viết chức năng của riêng bạn để làm như vậy nếu bạn thực sự muốn hành vi đó. Nhưng tôi không thể tưởng tượng nó rất hữu ích - nó vứt đi những dữ liệu có giá trị. –

Các vấn đề liên quan