Như các bạn đã đề cập, nó không xuất hiện để có thể để phần phát hành một loạt các trang dành riêng vì VirtualFree()
documentation trạng thái:
Nếu tham số dwFreeType là MEM_RELEASE, [lpAddress] phải là địa chỉ cơ sở được trả về bởi hàm VirtualAlloc khi vùng của trang [đã] được đặt trước.
cũng như:
Nếu dwFreeType tham số là MEM_RELEASE, [dwSize] phải là 0 (zero).
VirtualFree()
chính nó là một trình bao bọc mỏng của hàm hạt nhân NtFreeVirtualMemory()
. Its documentation page (giống như ZwFreeVirtualMemory()
) cũng có từ ngữ này.
Một công việc có thể là chia nhỏ một lần đặt phòng lớn với nhiều đặt phòng nhỏ hơn. Ví dụ: giả sử bạn thường đặt 8 MiB không gian địa chỉ ảo tại một thời điểm. Thay vào đó, bạn có thể cố gắng đặt trước phạm vi trong ba mươi hai đặt trước 256 KiB liền kề. Các phòng 256 KiB đầu tiên sẽ chứa một trường bit unsigned 32-bit, nơi ithứ bit được thiết lập nếu các thứ i phòng 256 KiB thu được: sản lượng
#define NOMINMAX
#include <windows.h>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define RESERVATION_SIZE (256*1024)
typedef struct st_first_reservation {
size_t reservation_size;
uint32_t rfield;
char premaining[0];
} st_first_reservation;
int main()
{
SYSTEM_INFO sys_info = { 0 };
GetSystemInfo(&sys_info);
assert((RESERVATION_SIZE % sys_info.dwPageSize) == 0);
void *vp = VirtualAlloc(NULL, 32*RESERVATION_SIZE, MEM_RESERVE, PAGE_NOACCESS);
if (VirtualFree(vp, 0, MEM_RELEASE) == 0) {
fprintf(stderr, "Error: VirtualFree() failed.\n");
return EXIT_FAILURE;
}
st_first_reservation *pfirst_reservation = (st_first_reservation *) VirtualAlloc(vp, RESERVATION_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (pfirst_reservation == NULL) {
pfirst_reservation = (st_first_reservation *) VirtualAlloc(NULL, RESERVATION_SIZE, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (pfirst_reservation == NULL) {
fprintf(stderr, "Error: VirtualAlloc() failed.\n");
return EXIT_FAILURE;
}
}
fprintf(stderr, "pfirst_reservation = 0x%p\n", (void *) pfirst_reservation);
pfirst_reservation->reservation_size = RESERVATION_SIZE;
pfirst_reservation->rfield = 1LU;
char *p = (char *) pfirst_reservation;
unsigned i = 1;
for (; i < 32; ++i) {
vp = VirtualAlloc(p += RESERVATION_SIZE, RESERVATION_SIZE, MEM_RESERVE, PAGE_NOACCESS);
if (vp != NULL) {
assert(((void *) vp) == p);
pfirst_reservation->rfield |= 1LU << i;
fprintf(stderr, "Obtained reservation #%u\n", i + 1);
} else {
fprintf(stderr, "Failed to obtain reservation #%u\n", i + 1);
}
}
fprintf(stderr, "pfirst_reservation->rfield = 0x%08x\n", pfirst_reservation->rfield);
return EXIT_SUCCESS;
}
mẫu:
pfirst_reservation = 0x009A0000
Obtained reservation #2
Obtained reservation #3
Obtained reservation #4
Obtained reservation #5
Obtained reservation #6
Obtained reservation #7
Obtained reservation #8
Obtained reservation #9
Obtained reservation #10
Obtained reservation #11
Obtained reservation #12
Obtained reservation #13
Obtained reservation #14
Obtained reservation #15
Obtained reservation #16
Obtained reservation #17
Obtained reservation #18
Obtained reservation #19
Obtained reservation #20
Obtained reservation #21
Obtained reservation #22
Obtained reservation #23
Obtained reservation #24
Obtained reservation #25
Obtained reservation #26
Obtained reservation #27
Obtained reservation #28
Obtained reservation #29
Obtained reservation #30
Obtained reservation #31
Obtained reservation #32
pfirst_reservation->rfield = 0xffffffff
EDIT: tôi đã tìm thấy rằng nó là tốt hơn để "tiền dự trữ" của ba mươi hai 256 KiB dao động cùng một lúc, miễn phí, và thứ vi cố gắng dự trữ lại nhiều nhất có thể.
Tôi đã cập nhật mã và đầu ra mẫu ở trên.
Trong môi trường đa luồng, mã có thể quay trở lại phân bổ "địa điểm bất kỳ đâu" của đặt chỗ đầu tiên. Có lẽ bạn nên thử đặt trước RESERVATION_SIZE
byte tại phạm vi được đặt trước sau đó giải phóng là 32*RESERVATION_SIZE
byte năm lần hoặc lâu hơn, cuối cùng sẽ quay trở lại phân bổ "địa điểm bất kỳ".
Toàn bộ điểm của bộ nhớ ảo là trừu tượng hóa công cụ này và để thỏa thuận hạt nhân với vị trí bộ nhớ. –
Ứng dụng của bạn có cần phát hành các trang của bộ nhớ ảo hay không; bạn đang chạy ra khỏi không gian địa chỉ ảo? –
@DanielTrebbien: Tình hình là như sau .. Tôi cần một khu vực mới, vì vậy tôi cố gắng phân bổ nó với VirtualAlloc. Tuy nhiên, VirtualAlloc ném một bộ nhớ ngoài. Đồng thời, vì một số siêu dữ liệu tôi giữ bản thân mình, tôi biết rằng một số khu vực nhất định chỉ có một nửa. Bây giờ tôi muốn thu nhỏ hoặc phân bổ lại những khu vực đó với giá rẻ cho đến khi tôi có trí nhớ một lần nữa. – cib