-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Description
Bug report
tuple.__sizeof__, int.__sizeof__, and bool.__sizeof__ incorrectly returns a size using an algorithm that assumes the ob_item / ob_digit array is size 0 when ob_size is 0, when this is not true.
print((0).__sizeof__())
>> 24
print((1).__sizeof__())
>> 28This result of __sizeof__ suggests that int(0) has an ob_digit array size of 0, and thus 4 less bytes (considering array dtype of c_uint32). However, this is not correct.
https://github.com/python/cpython/blob/3.11/Include/cpython/longintrepr.h#L79-L82
Code paths for the creation of int(0) and other PyVarObject types all initialize with an array of size 1. Such the struct of int(0) holds a c_uint32 array of size 1, and element [0] of 0.
The result 24 of (0).__sizeof__() suggests that this array does not exist for sizing purposes. This seems to be misleading for performance calculations on memory size, and creates unsafe scenarios when moving memory.
Implementations of __sizeof__
(int) (bool also inherits this)
https://github.com/python/cpython/blob/main/Objects/longobject.c#L5876-L5884
res = offsetof(PyLongObject, ob_digit) + Py_ABS(Py_SIZE(self))*sizeof(digit);(tuple)
https://github.com/python/cpython/blob/main/Objects/typeobject.c#L5929-L5942
Your environment
- CPython versions tested on: 3.11.1 and main branch
- Operating system and architecture: Windows and macOS