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__())
>> 28
This 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