Đống ngăn xếp Python
Quản lý bộ nhớ trong Python liên quan đến một đống riêng chứa tất cả các đối tượng Python và cấu trúc dữ liệu. Việc quản lý vùng riêng tư này được đảm bảo nội bộ bởi trình quản lý bộ nhớ Python. Trình quản lý bộ nhớ Python có các thành phần khác nhau xử lý các khía cạnh quản lý lưu trữ động khác nhau, như chia sẻ, phân đoạn, phân bổ trước hoặc bộ nhớ đệm Show
Ở mức thấp nhất, bộ cấp phát bộ nhớ thô đảm bảo rằng có đủ chỗ trong vùng riêng tư để lưu trữ tất cả dữ liệu liên quan đến Python bằng cách tương tác với trình quản lý bộ nhớ của hệ điều hành. Ngoài bộ cấp phát bộ nhớ thô, một số bộ cấp phát dành riêng cho đối tượng hoạt động trên cùng một vùng nhớ và thực hiện các chính sách quản lý bộ nhớ riêng biệt phù hợp với đặc thù của từng loại đối tượng. Ví dụ: các đối tượng số nguyên được quản lý khác nhau trong heap so với chuỗi, bộ dữ liệu hoặc từ điển vì số nguyên bao hàm các yêu cầu lưu trữ khác nhau và sự đánh đổi giữa tốc độ/không gian. Do đó, trình quản lý bộ nhớ Python ủy thác một số công việc cho bộ cấp phát dành riêng cho đối tượng, nhưng đảm bảo rằng bộ cấp phát sau hoạt động trong giới hạn của vùng riêng tư Điều quan trọng là phải hiểu rằng việc quản lý heap Python được thực hiện bởi chính trình thông dịch và người dùng không có quyền kiểm soát nó, ngay cả khi họ thường xuyên thao tác các con trỏ đối tượng tới các khối bộ nhớ bên trong heap đó. Việc phân bổ không gian heap cho các đối tượng Python và các bộ đệm bên trong khác được trình quản lý bộ nhớ Python thực hiện theo yêu cầu thông qua các hàm API Python/C được liệt kê trong tài liệu này Để tránh hỏng bộ nhớ, người viết tiện ích mở rộng không bao giờ được thử thao tác trên các đối tượng Python bằng các hàm do thư viện C xuất ra. PyObject *res; char *buf = (char *) malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); ...Do some I/O operation involving buf... res = PyBytes_FromString(buf); free(buf); /* malloc'ed */ return res; Trong ví dụ này, yêu cầu bộ nhớ cho bộ đệm I/O được xử lý bởi bộ cấp phát thư viện C. Kết quả là trình quản lý bộ nhớ Python chỉ liên quan đến việc phân bổ đối tượng byte được trả về Tuy nhiên, trong hầu hết các trường hợp, nên phân bổ bộ nhớ cụ thể từ heap Python vì heap nằm dưới sự kiểm soát của trình quản lý bộ nhớ Python. Ví dụ: điều này là bắt buộc khi trình thông dịch được mở rộng với các loại đối tượng mới được viết bằng C. Một lý do khác để sử dụng heap Python là mong muốn thông báo cho trình quản lý bộ nhớ Python về nhu cầu bộ nhớ của mô-đun mở rộng. Ngay cả khi bộ nhớ được yêu cầu được sử dụng riêng cho các mục đích nội bộ, có tính đặc biệt cao, việc ủy quyền tất cả các yêu cầu bộ nhớ cho trình quản lý bộ nhớ Python sẽ khiến trình thông dịch có hình ảnh chính xác hơn về toàn bộ dung lượng bộ nhớ của nó. Do đó, trong một số trường hợp nhất định, trình quản lý bộ nhớ Python có thể kích hoạt hoặc không kích hoạt các hành động thích hợp, như thu gom rác, nén bộ nhớ hoặc các quy trình phòng ngừa khác. Lưu ý rằng bằng cách sử dụng bộ cấp phát thư viện C như trong ví dụ trước, bộ nhớ được cấp phát cho bộ đệm I/O thoát hoàn toàn khỏi trình quản lý bộ nhớ Python Xem thêm Biến môi trường có thể được sử dụng để định cấu hình bộ cấp phát bộ nhớ được sử dụng bởi Python Biến môi trường có thể được sử dụng để in số liệu thống kê mỗi khi một đấu trường đối tượng pymalloc mới được tạo và khi tắt máy Tên miền cấp phátTất cả các chức năng phân bổ thuộc về một trong ba “miền” khác nhau (xem thêm). Các miền này đại diện cho các chiến lược phân bổ khác nhau và được tối ưu hóa cho các mục đích khác nhau. Chi tiết cụ thể về cách mọi miền phân bổ bộ nhớ hoặc chức năng nội bộ mà mỗi miền gọi được coi là chi tiết triển khai, nhưng để gỡ lỗi, bạn có thể tìm thấy bảng đơn giản hóa tại. Không có yêu cầu khó sử dụng bộ nhớ được trả về bởi các hàm cấp phát thuộc về một miền nhất định chỉ cho các mục đích được gợi ý bởi miền đó (mặc dù đây là phương pháp được khuyến nghị). Ví dụ: người ta có thể sử dụng bộ nhớ được trả về để phân bổ các đối tượng Python hoặc bộ nhớ được trả về để phân bổ bộ nhớ cho bộ đệm Ba miền phân bổ là
Khi giải phóng bộ nhớ được cấp phát trước đó bởi các chức năng cấp phát thuộc một miền nhất định, phải sử dụng các chức năng cấp phát cụ thể phù hợp. Ví dụ: phải được sử dụng để giải phóng bộ nhớ được cấp phát bằng cách sử dụng Giao diện bộ nhớ thôCác bộ chức năng sau đây là các trình bao bọc cho bộ cấp phát hệ thống. Các chức năng này an toàn cho luồng, không cần phải giữ Việc sử dụng các chức năng sau. Mới trong phiên bản 3. 4 void *PyMem_RawMalloc(size_t n)Cấp phát n byte và trả về một con trỏ loại void* cho bộ nhớ được cấp phát hoặc PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1 . Yêu cầu các byte bằng 0 trả về một con trỏ khác biệt không phải ____2_______1 nếu có thể, như thể thay vào đó PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;3 đã được gọi. Bộ nhớ sẽ không được khởi tạo theo bất kỳ cách nàovoid *PyMem_RawCalloc(size_t nelem, size_t elsize) Cấp phát các phần tử nelem, mỗi phần tử có kích thước theo byte là elsize và trả về một con trỏ loại void* . Bộ nhớ được khởi tạo bằng không. Yêu cầu các phần tử bằng 0 hoặc các phần tử có kích thước byte bằng 0 trả về một con trỏ không phải ______2_______1 riêng biệt nếu có thể, như thể thay vào đó, PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;6 đã được gọi Mới trong phiên bản 3. 5 void *PyMem_RawRealloc(void *p, size_t n)Thay đổi kích thước khối bộ nhớ được trỏ tới bởi p thành n byte. Nội dung sẽ không thay đổi ở mức tối thiểu của kích thước cũ và mới Nếu p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, cuộc gọi tương đương với PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;8; Trừ khi p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, nó phải được trả về bởi một lệnh gọi trước đó tới , hoặc Nếu yêu cầu không thành công, trả về PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1 và p vẫn là một con trỏ hợp lệ tới vùng bộ nhớ trước đóvoid PyMem_RawFree(void *p) Giải phóng khối bộ nhớ được trỏ tới bởi p, khối này phải được trả về bởi lệnh gọi trước đó tới , hoặc. Mặt khác, hoặc nếu char *buf1 = PyMem_New(char, BUFSIZ); char *buf2 = (char *) malloc(BUFSIZ); char *buf3 = (char *) PyMem_Malloc(BUFSIZ); ... PyMem_Del(buf3); /* Wrong -- should be PyMem_Free() */ free(buf2); /* Right -- allocated via malloc() */ free(buf1); /* Fatal -- should be PyMem_Del() */9 đã được gọi trước đó, hành vi không xác định sẽ xảy ra Nếu p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, không có thao tác nào được thực hiện Giao diện bộ nhớCác bộ chức năng sau đây, được lập mô hình theo tiêu chuẩn ANSI C, nhưng chỉ định hành vi khi yêu cầu byte bằng 0, có sẵn để cấp phát và giải phóng bộ nhớ khỏi heap Python Việc sử dụng Cảnh báo Phải được tổ chức khi sử dụng các chức năng này Đã thay đổi trong phiên bản 3. 6. Bộ cấp phát mặc định hiện là pymalloc thay vì hệ thống một phần của Cấp phát n byte và trả về một con trỏ loại void* cho bộ nhớ được cấp phát hoặc PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1 . Yêu cầu các byte bằng 0 trả về một con trỏ không phải ____2_______1 nếu có thể, như thể thay vào đó, Một phần của kể từ phiên bản 3. 7 Cấp phát các phần tử nelem, mỗi phần tử có kích thước theo byte là elsize và trả về một con trỏ loại void* . Bộ nhớ được khởi tạo bằng không. Yêu cầu các phần tử bằng 0 hoặc các phần tử có kích thước byte bằng 0 trả về một con trỏ không phải ______2_______1 riêng biệt nếu có thể, như thể thay vào đó, Mới trong phiên bản 3. 5 void *PyMem_Realloc(void *p, size_t n)một phần của Thay đổi kích thước khối bộ nhớ được trỏ tới bởi p thành n byte. Nội dung sẽ không thay đổi ở mức tối thiểu của kích thước cũ và mới Nếu p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, cuộc gọi tương đương với malloc() 9; Trừ khi p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, nó phải được trả về bởi một lệnh gọi trước đó tới , hoặc Nếu yêu cầu không thành công, trả về PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1 và p vẫn là một con trỏ hợp lệ tới vùng bộ nhớ trước đóvoid PyMem_Free(void *p) một phần của Giải phóng khối bộ nhớ được trỏ tới bởi p, khối này phải được trả về bởi lệnh gọi trước đó tới , hoặc. Mặt khác, hoặc nếu Nếu p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, không có thao tác nào được thực hiện Các macro hướng loại sau đây được cung cấp để thuận tiện. Lưu ý rằng LOẠI đề cập đến bất kỳ loại C nào LOẠI *PyMem_New(LOẠI, size_t n)Tương tự như , nhưng phân bổ _______105_______3 byte bộ nhớ. Trả về một con trỏ được truyền tới TYPE* . Bộ nhớ sẽ không được khởi tạo theo bất kỳ cách nào. LOẠI *PyMem_Resize(void *p, TYPE, size_t n)Tương tự như , nhưng khối bộ nhớ được thay đổi kích thước thành PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1 trong trường hợp thất bại. Đây là macro tiền xử lý C; . Lưu giá trị ban đầu của p để tránh mất bộ nhớ khi xử lý lỗi void PyMem_Del(void *p)Giống như Ngoài ra, các bộ macro sau được cung cấp để gọi trực tiếp bộ cấp phát bộ nhớ Python mà không liên quan đến các hàm API C được liệt kê ở trên. Tuy nhiên, lưu ý rằng việc sử dụng chúng không duy trì khả năng tương thích nhị phân trên các phiên bản Python và do đó không được dùng trong các mô-đun mở rộng
Cấp phát đối tượngCác bộ chức năng sau đây, được lập mô hình theo tiêu chuẩn ANSI C, nhưng chỉ định hành vi khi yêu cầu byte bằng 0, có sẵn để cấp phát và giải phóng bộ nhớ khỏi heap Python Ghi chú Không có gì đảm bảo rằng bộ nhớ do các bộ cấp phát này trả về có thể được truyền thành công tới một đối tượng Python khi chặn các hàm cấp phát trong miền này bằng các phương pháp được mô tả trong phần Việc sử dụng Cảnh báo Phải được tổ chức khi sử dụng các chức năng này void *PyObject_Malloc(size_t n)một phần của Cấp phát n byte và trả về một con trỏ loại void* cho bộ nhớ được cấp phát hoặc PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1 . Yêu cầu các byte bằng 0 trả về một con trỏ khác biệt không phải ____2_______1 nếu có thể, như thể thay vào đó, Một phần của kể từ phiên bản 3. 7 Cấp phát các phần tử nelem, mỗi phần tử có kích thước theo byte là elsize và trả về một con trỏ loại void* . Bộ nhớ được khởi tạo bằng không. Yêu cầu các phần tử bằng 0 hoặc các phần tử có kích thước byte bằng 0 trả về một con trỏ không phải ______2_______1 riêng biệt nếu có thể, như thể thay vào đó, Mới trong phiên bản 3. 5 void *PyObject_Realloc(void *p, size_t n)một phần của Thay đổi kích thước khối bộ nhớ được trỏ tới bởi p thành n byte. Nội dung sẽ không thay đổi ở mức tối thiểu của kích thước cũ và mới Nếu p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, cuộc gọi tương đương với PYTHONMALLOC 1; Trừ khi p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, nó phải được trả về bởi một lệnh gọi trước đó tới , hoặc Nếu yêu cầu không thành công, trả về PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1 và p vẫn là một con trỏ hợp lệ tới vùng bộ nhớ trước đóvoid PyObject_Free(void *p) một phần của Giải phóng khối bộ nhớ được trỏ tới bởi p, khối này phải được trả về bởi lệnh gọi trước đó tới , hoặc. Mặt khác, hoặc nếu Nếu p là PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;1, không có thao tác nào được thực hiện Bộ cấp phát bộ nhớ mặc địnhBộ cấp phát bộ nhớ mặc định Cấu hình Tên PyMem_RawMalloc PyMem_Malloc PyObject_Malloc Phát hành bản dựng
bản dựng gỡ lỗi
Phát hành bản dựng, không có pymalloc PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;02
Bản dựng gỡ lỗi, không có pymalloc PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;06
Huyền thoại
Tùy chỉnh cấp phát bộ nhớMới trong phiên bản 3. 4 type PyMemAllocatorExCấu trúc được sử dụng để mô tả bộ cấp phát khối bộ nhớ. Cấu trúc có các trường sau Đồng ruộng Nghĩa PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;17 ngữ cảnh người dùng được chuyển làm đối số đầu tiên PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;18 phân bổ một khối bộ nhớ PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;19 phân bổ một khối bộ nhớ được khởi tạo bằng số không PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;20 phân bổ hoặc thay đổi kích thước khối bộ nhớ PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;21 giải phóng một khối bộ nhớ Đã thay đổi trong phiên bản 3. 5. Cấu trúc PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;22 đã được đổi tên thành và một trường PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;24 mới đã được thêm vào. type PyMemAllocatorDomain Enum được sử dụng để xác định miền cấp phát. tên miền PYMEM_DOMAIN_RAWChức năng Chức năng
Chức năng Nhận bộ cấp phát khối bộ nhớ của miền đã chỉ định void PyMem_SetAllocator( miền , *allocator)Đặt bộ cấp phát khối bộ nhớ của miền đã chỉ định Bộ cấp phát mới phải trả về một con trỏ không phải ______2_______1 riêng biệt khi yêu cầu byte bằng 0 Đối với miền PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;38, bộ cấp phát phải an toàn theo luồng. cái không được giữ khi bộ cấp phát được gọi Nếu bộ cấp phát mới không phải là hook (không gọi bộ cấp phát trước đó), hàm phải được gọi để cài đặt lại các hook gỡ lỗi ở trên cùng trên bộ cấp phát mới Xem thêm và Cảnh báo có hợp đồng sau void PyMem_SetupDebugHooks(void) Thiết lập để phát hiện lỗi bộ nhớ Gỡ lỗi móc trên bộ cấp phát bộ nhớ PythonKhi nào, hàm được gọi để thiết lập móc gỡ lỗi trên bộ cấp phát bộ nhớ Python để phát hiện lỗi bộ nhớ Biến môi trường có thể được sử dụng để cài đặt móc gỡ lỗi trên Python được biên dịch ở chế độ phát hành (ví dụ:. PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;47) Chức năng này có thể được sử dụng để đặt móc gỡ lỗi sau khi gọi Các móc gỡ lỗi này lấp đầy các khối bộ nhớ được cấp phát động bằng các mẫu bit đặc biệt, dễ nhận biết. Bộ nhớ mới được cấp phát chứa đầy byte PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;50 ( PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;51), bộ nhớ được giải phóng chứa đầy byte PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;52 ( PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;53). Các khối bộ nhớ được bao quanh bởi “các byte bị cấm” chứa đầy byte PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;54 ( PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;55). Các chuỗi byte này không có khả năng là địa chỉ hợp lệ, số float hoặc chuỗi ASCII kiểm tra thời gian chạy
Khi xảy ra lỗi, móc gỡ lỗi sử dụng mô-đun để truy xuất nguồn gốc nơi một khối bộ nhớ được phân bổ. Traceback chỉ được hiển thị nếu đang theo dõi phân bổ bộ nhớ Python và khối bộ nhớ đã được theo dõi Đặt S = PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;64. PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;65 byte được thêm vào mỗi đầu của mỗi khối N byte được yêu cầu. Bố cục bộ nhớ giống như vậy, trong đó p đại diện cho địa chỉ được trả về bởi hàm giống malloc hoặc giống realloc ( PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;66 có nghĩa là lát byte từ bao gồm PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;67 cho đến loại trừ PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;68; lưu ý rằng cách xử lý các chỉ số âm khác với lát Python PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;69 Số byte ban đầu được yêu cầu. Đây là size_t, big-endian (dễ đọc hơn trong kết xuất bộ nhớ) PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;70 Mã định danh API (ký tự ASCII)
PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;77 Bản sao của PYMEM_FORBIDDENBYTE. Được sử dụng để bắt ghi dưới và đọc PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;78 Bộ nhớ được yêu cầu, chứa đầy các bản sao của PYMEM_CLEANBYTE, được sử dụng để bắt tham chiếu đến bộ nhớ chưa được khởi tạo. Khi một hàm giống realloc được gọi yêu cầu khối bộ nhớ lớn hơn, các byte dư thừa mới cũng được lấp đầy bằng PYMEM_CLEANBYTE. Khi một chức năng giống như tự do được gọi, chúng sẽ được ghi đè bằng PYMEM_DEADBYTE, để bắt tham chiếu đến bộ nhớ được giải phóng. Khi một chức năng giống như realloc được gọi yêu cầu một khối bộ nhớ nhỏ hơn, các byte cũ dư thừa cũng được lấp đầy bằng PYMEM_DEADBYTE PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;79 Bản sao của PYMEM_FORBIDDENBYTE. Được sử dụng để ghi đè và đọc PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;80 Chỉ được sử dụng nếu macro PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;81 được xác định (không được xác định theo mặc định) Một số sê-ri, được tăng thêm 1 trên mỗi lần gọi hàm giống malloc hoặc giống realloc. Big-endian PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;82. Nếu “bộ nhớ kém” được phát hiện sau đó, số sê-ri sẽ cung cấp một cách tuyệt vời để đặt điểm dừng trong lần chạy tiếp theo, để ghi lại khoảnh khắc mà khối này được chuyển đi. Hàm tĩnh bumpserialno() trong obmalloc. c là nơi duy nhất số sê-ri được tăng lên và tồn tại để bạn có thể dễ dàng đặt điểm dừng như vậy Trước tiên, chức năng giống như realloc hoặc giống như tự do sẽ kiểm tra xem các byte PYMEM_FORBIDDENBYTE ở mỗi đầu có còn nguyên vẹn không. Nếu chúng đã bị thay đổi, đầu ra chẩn đoán được ghi vào thiết bị lỗi chuẩn và chương trình bị hủy bỏ qua Py_FatalError(). Chế độ lỗi chính khác đang gây ra lỗi bộ nhớ khi chương trình đọc một trong các mẫu bit đặc biệt và cố gắng sử dụng nó làm địa chỉ. Sau đó, nếu bạn vào trình gỡ lỗi và nhìn vào đối tượng, bạn có thể thấy rằng nó hoàn toàn chứa đầy PYMEM_DEADBYTE (có nghĩa là bộ nhớ được giải phóng đang được sử dụng) hoặc PYMEM_CLEANBYTE (có nghĩa là bộ nhớ chưa được khởi tạo đang được sử dụng) Đã thay đổi trong phiên bản 3. 6. Hàm này hiện cũng hoạt động trên Python được biên dịch ở chế độ phát hành. Khi có lỗi, các móc gỡ lỗi hiện sử dụng để truy xuất nguồn gốc nơi một khối bộ nhớ được phân bổ. Các móc gỡ lỗi hiện cũng kiểm tra xem GIL có được giữ hay không khi các chức năng của tên miền PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;58 và PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;60 được gọi. Đã thay đổi trong phiên bản 3. 8. Các mẫu byte PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;87 ( PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;51), PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;89 ( PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;53) và PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;91 ( PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;55) đã được thay thế bằng PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;50, PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;52 và PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;54 để sử dụng các giá trị giống như Windows CRT debug malloc() và free() . Bộ cấp phát pymallocPython có bộ cấp phát pymalloc được tối ưu hóa cho các đối tượng nhỏ (nhỏ hơn hoặc bằng 512 byte) với thời gian tồn tại ngắn. Nó sử dụng ánh xạ bộ nhớ được gọi là "đấu trường" với kích thước cố định là 256 KiB. Nó quay trở lại và dành cho phân bổ lớn hơn 512 byte pymalloc là của PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;60 (ví dụ:. ) và PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;58 (ví dụ:. ) tên miền Bộ phân bổ đấu trường sử dụng các chức năng sau
Trình cấp phát này bị tắt nếu Python được định cấu hình với tùy chọn. Nó cũng có thể bị vô hiệu hóa trong thời gian chạy bằng cách sử dụng biến môi trường (ví dụ:. PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;12) Tùy chỉnh Trình phân bổ đấu trường pymallocMới trong phiên bản 3. 4 loại PyObjectArenaAllocatorCấu trúc được sử dụng để mô tả một bộ phân bổ đấu trường. Cấu trúc có ba trường Đồng ruộng Nghĩa PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res;17 ngữ cảnh người dùng được chuyển làm đối số đầu tiên PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;14 phân bổ một đấu trường có kích thước byte PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;15 giải phóng một đấu trường void PyObject_GetArenaAllocator( *cấp phát)Nhận phân bổ đấu trường void PyObject_SetArenaAllocator( *cấp phát)Đặt bộ phân bổ đấu trường API tramalloc CMới trong phiên bản 3. 7 int PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, size_t size)Theo dõi một khối bộ nhớ được phân bổ trong mô-đun Trả về PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;17 nếu thành công, trả về PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;18 nếu lỗi (không thể cấp phát bộ nhớ để lưu dấu vết). Quay lại PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;19 nếu dấu vết bị vô hiệu hóa Nếu khối bộ nhớ đã được theo dõi, hãy cập nhật dấu vết hiện có int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)Bỏ theo dõi một khối bộ nhớ được phân bổ trong mô-đun. Không làm gì nếu khối không được theo dõi Trả lại PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;19 nếu tracemalloc bị vô hiệu hóa, nếu không thì trả lại PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res;17 ví dụĐây là ví dụ từ phần , được viết lại để bộ đệm I/O được phân bổ từ vùng heap Python bằng cách sử dụng tập hàm đầu tiên PyObject *res; char *buf = (char *) PyMem_Malloc(BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Free(buf); /* allocated with PyMem_Malloc */ return res; Mã tương tự sử dụng bộ chức năng định hướng kiểu PyObject *res; char *buf = PyMem_New(char, BUFSIZ); /* for I/O */ if (buf == NULL) return PyErr_NoMemory(); /* ...Do some I/O operation involving buf.. */ res = PyBytes_FromString(buf); PyMem_Del(buf); /* allocated with PyMem_New */ return res; Lưu ý rằng trong hai ví dụ trên, bộ đệm luôn được thao tác thông qua các hàm thuộc cùng một tập hợp. Thật vậy, bắt buộc phải sử dụng cùng một họ API bộ nhớ cho một khối bộ nhớ nhất định, do đó rủi ro trộn lẫn các bộ cấp phát khác nhau được giảm đến mức tối thiểu. Chuỗi mã sau có hai lỗi, một trong số đó được gắn nhãn là nghiêm trọng vì nó trộn lẫn hai trình cấp phát khác nhau hoạt động trên các vùng khác nhau char *buf1 = PyMem_New(char, BUFSIZ); char *buf2 = (char *) malloc(BUFSIZ); char *buf3 = (char *) PyMem_Malloc(BUFSIZ); ... PyMem_Del(buf3); /* Wrong -- should be PyMem_Free() */ free(buf2); /* Right -- allocated via malloc() */ free(buf1); /* Fatal -- should be PyMem_Del() */ Ngoài các chức năng nhằm xử lý các khối bộ nhớ thô từ heap Python, các đối tượng trong Python được cấp phát và giải phóng với , và Python có sử dụng ngăn xếp hoặc đống không?Cấp phát bộ nhớ trong Python
. The function calls and the references are stored in the stack memory whereas all the value objects are stored in the heap memory.
Python có ngăn xếp bộ nhớ không?Bộ nhớ ngăn xếp
. Khung ngăn xếp này sẽ xử lý tất cả các biến của phương thức. Sau khi phương thức được trả về, khung ngăn xếp sẽ tự động bị hủy. Lưu ý rằng khung ngăn xếp cũng chịu trách nhiệm đặt phạm vi cho các biến của phương thức. When a method is called in Python, a stack frame is allocated. This stack frame will handle all the variables of the method. After the method is returned, the stack frame is automatically destroyed. Note that the stack frame is also responsible for setting the scope for the variables of a method.
Sử dụng stack hay heap tốt hơn?Cấp phát bộ nhớ ngăn xếp được coi là an toàn hơn so với cấp phát bộ nhớ heap vì dữ liệu được lưu trữ chỉ có thể được truy cập bởi luồng chủ sở hữu. Cấp phát và hủy cấp phát bộ nhớ nhanh hơn so với cấp phát bộ nhớ Heap. Bộ nhớ ngăn xếp có ít dung lượng lưu trữ hơn so với bộ nhớ Heap.
Không gian ngăn xếp trong Python là gì?Không gian heap trong Python chủ yếu duy trì tất cả các đối tượng và cấu trúc dữ liệu, trong khi đối tác của nó, không gian ngăn xếp, chứa tất cả các tham chiếu đến các đối tượng trong không gian heap. Khi một đối tượng được cập nhật, giá trị mới được ghi ở một vị trí mới và biến được tham chiếu đến địa chỉ mới |