Căn chỉnh malloc
là posix_memalign
, OK, nhưng còn liên kết realloc
thì sao? realloc
giữ nguyên căn chỉnh hay cách đảm bảo rằng bộ nhớ được phân bổ lại có cùng sự liên kết? Giả sử Linux và x86_64.Realloc có giữ liên kết bộ nhớ của posix_memalign không?
Trả lời
Không, realloc
trên bộ nhớ được trả lại từ posix_memalign
không được đảm bảo bởi ISO hoặc POSIX để duy trì cùng một căn chỉnh. A realloc
có thể chỉ cần mở rộng khối hiện tại tại cùng một địa chỉ nhưng nó cũng có thể di chuyển khối đến một địa chỉ khác có căn chỉnh ít chặt chẽ hơn so với ban đầu.
Nếu bạn muốn căn chỉnh giống nhau, tốt nhất nên phân bổ một khối khác và sao chép dữ liệu.
Có, thật không may, không có hàm posix_memalign_realloc
trong Đặc tả UNIX đơn.
Nếu bạn không muốn phải trải qua những rắc rối của việc sao chép dữ liệu mỗi thời gian, bạn có thể thử các realloc
(a) và, nếu sự liên kết đó đã không được như mong đợi, sau đó và chỉ sau đó gọi posix_memalign
để nhận địa chỉ được căn chỉnh chính xác và sao chép dữ liệu vào đó, giải phóng địa chỉ cũ khi hoàn tất.
này có thể dẫn đến:
- zero bản (nếu khối hiện tại có thể được mở rộng tại chỗ);
- một bản sao (nếu
realloc
bản sao nhưng sẽ xảy ra để cung cấp cho bạn một khối được căn chỉnh chính xác); hoặc - hai bản sao (nếu
realloc
bản sao và sau đó bạn cũng phải sao chép do không điều chỉnh).
Nó có thể cũng dẫn đến ít sao chép hơn được chỉ định tùy thuộc vào việc triển khai quản lý bộ nhớ cơ bản. Ví dụ, một "bản sao" có thể đơn giản liên quan đến việc tái tạo các khối bộ nhớ thay vì di chuyển dữ liệu.
Vì vậy, bạn có thể muốn giữ một số thống kê để xem liệu chương trình này có đáng giá hay không.
(a) Chỉ cần ghi nhớ rằng không phải POSIX hay Linux trang người đàn ông chỉ định hay không, bạn thậm chí có thể vượt qua những gợi ý để realloc
, duy nhất mà bạn có thể vượt qua chúng để free
.
Tuy nhiên, dựa trên mã nguồn libc GNU hiện tại, nó xuất hiện để làm việc, mặc dù điều đó không đảm bảo nó sẽ tiếp tục làm việc trong tương lai :-)
sợ hãi của tôi là nó sẽ cấp phát bộ nhớ thông thường (liên kết tiêu chuẩn) và trả lại một địa chỉ offset (ví dụ, không phải địa chỉ actaul được cấp phát, nhưng một trong số N
byte vượt quá điều đó) mà free
đủ thông minh để quay trở lại địa chỉ thực tế trước khi dệt phép thuật của nó.
Một cách để làm điều đó là lưu trữ địa chỉ thực tế ngay trước địa chỉ được trả lại mặc dù điều này tất nhiên sẽ dẫn đến lãng phí ngay cả đối với phân bổ thường xuyên.
Trong trường hợp đó, free
có thể đã được thực hiện thông minh (kể từ khi thông số kỹ thuật nói nó phải có khả năng xử lý việc phân bổ thực hiện bằng cách posix_memalign
) nhưng realloc
có thể không được trao tình báo tương tự (kể từ khi tài liệu là im lặng về vấn đề đó).
Tuy nhiên, dựa trên GNU glibc 2.14.1, nó thực sự phân bổ bộ nhớ nhiều hơn mức cần thiết rồi đấu với đấu trường để giải phóng không gian trước và sau không gian, để địa chỉ trả về là địa chỉ "thực", có thể sử dụng bởi free
hoặc realloc
.
Nhưng, như đã nêu, tài liệu không đảm bảo điều này.
Câu trả lời này không đúng theo một cách quan trọng: realloc thường không sao chép ngay cả khi vùng bộ nhớ di chuyển. Tôi nghĩ rằng nếu không có đủ chỗ ở địa chỉ bộ nhớ hiện tại để mở rộng bộ đệm - các trang sẽ được ánh xạ lại để tránh một bản sao. Vì vậy, nó sẽ không phải là bản sao, không bản sao, một bản sao. –
@RafaelBaptista, bạn đang bối rối một số * triển khai * với các tiêu chuẩn *. * Có * không có gì * trong các tiêu chuẩn (ISO/POSIX) yêu cầu mọi thứ xảy ra như thế nào trong các bản cover. Tuy nhiên, có vẻ như câu hỏi đã được thay đổi sau khi tôi trả lời giả sử Linux thu hẹp lĩnh vực này (nhưng ít hơn bạn có thể nghĩ vì Linux chạy trên nhiều phần cứng khác nhau với các tùy chọn MMU cực kỳ khác nhau). Sẽ điều chỉnh câu trả lời cho phù hợp. – paxdiablo
realloc hoạt động giống như malloc, do đó bộ nhớ được trả về bởi realloc có cùng một ràng buộc liên kết của malloc.
Nếu bạn nhìn vào mã nguồn glibc cho realloc, nó gọi trực tiếp đến malloc. Vì vậy, bộ nhớ được sắp xếp theo cùng một cách như malloc.
Xin lỗi, tôi nên thêm. Trong nguồn, nếu có thêm không gian heap trong vị trí đã được chỉ định bởi bộ nhớ malloc'd ban đầu thì nó chỉ phân bổ đống bổ sung ở cuối kích thước phân bổ ban đầu mà không cần gọi malloc. Điều này rõ ràng sẽ không thay đổi sự liên kết. –
Không - nếu bạn cần căn chỉnh cụ thể, ví dụ: cho dữ liệu SIMD, sau đó không sử dụng realloc. –
Vì vậy, nếu tôi cần "liên kết realloc", tôi phải tự do và posix_memalign bộ nhớ mới, phải không? – Cartesius00
Có - bạn thậm chí có thể thực hiện 'posix_memrealloc' của riêng bạn như thế này nếu bạn thực sự muốn. –