-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PEP 670: Convert _PyObject_SIZE() and _PyObject_VAR_SIZE() macros to functions #99845
Comments
Aha, |
@corona10 @erlend-aasland @serhiy-storchaka: Are you ok to use an unsigned type for _PyObject_SIZE() and _PyObject_VAR_SIZE() result? See PR #99846 and PR #99847 for concrete changes to prepare converting these macros to functions. |
In PyPI top 5000 projects, _PyObject_SIZE() and _PyObject_VAR_SIZE() are used with signed and unsigned types. numpy uses unsigned:
Cython gdb plugin treats _PyObject_VAR_SIZE() macro result as unsigned:
JPype uses signed and unsigned types:
frozendict uses signed type (copy of CPython Objects/dictobject.c which also uses signed types currently):
pickle uses signed:
recordclass uses signed:
Nuitka uses unsigned:
pyobjc-core casts implicitly
|
I created PR #99848 for Objects/dictobject.c. |
The final change should be PR #99850 which convert the two macros to functions. |
* Change _PyDict_KeysSize() and shared_keys_usable_size() return type from signed (Py_ssize_t) to unsigned (size_t) type. * new_values() argument type is now unsigned (size_t). * init_inline_values() now uses size_t rather than int for the 'i' iterator variable. * type.__sizeof__() implementation now uses unsigned (size_t) type.
* code_sizeof() now uses an unsigned type (size_t) to compute the result. * Fix _PyObject_ComputedDictPointer(): cast _PyObject_VAR_SIZE() to Py_ssize_t, rather than long: it's a different type on 64-bit Windows. * Clarify that _PyObject_VAR_SIZE() uses an unsigned type (size_t).
I was confused by the "SIZE" name:
IMO for bytes, it's better to use unsigned numbers. In the Python API, it's not an issue, it's an object. For example, |
The implementation of __sizeof__() methods using _PyObject_SIZE() now use an unsigned type (size_t) to compute the size, rather than a signed type (Py_ssize_t). Cast explicitly signed (Py_ssize_t) values to unsigned type (Py_ssize_t).
Convert macros to static inline functions to avoid macro pitfalls, like duplication of side effects: * _PyObject_SIZE() * _PyObject_VAR_SIZE() The result type is size_t (unsigned).
Cast size_t to Py_ssize_t, rather than casting it to long. On 64-bit Windows, long is 32-bit whereas Py_ssize_t is 64-bit.
* main: (112 commits) pythongh-99894: Ensure the local names don't collide with the test file in traceback suggestion error checking (python#99895) pythongh-99612: Fix PyUnicode_DecodeUTF8Stateful() for ASCII-only data (pythonGH-99613) Doc: Add summary line to isolation_level & autocommit sqlite3.connect params (python#99917) pythonGH-98906 ```re``` module: ```search() vs. match()``` section should mention ```fullmatch()``` (pythonGH-98916) pythongh-89189: More compact range iterator (pythonGH-27986) bpo-47220: Document the optional callback parameter of weakref.WeakMethod (pythonGH-25491) pythonGH-99905: Fix output of misses in summarize_stats.py execution counts (pythonGH-99906) pythongh-99845: PEP 670: Convert PyObject macros to functions (python#99850) pythongh-99845: Use size_t type in __sizeof__() methods (python#99846) pythonGH-99877) Fix typo in exception message in `multiprocessing.pool` (python#99900) pythongh-87092: move all localsplus preparation into separate function called from assembler stage (pythonGH-99869) pythongh-99891: Fix infinite recursion in the tokenizer when showing warnings (pythonGH-99893) pythongh-99824: Document that sqlite3.connect implicitly open a transaction if autocommit=False (python#99825) pythonGH-81057: remove static state from suggestions.c (python#99411) Improve zip64 limit error message (python#95892) pythongh-98253: Break potential reference cycles in external code worsened by typing.py lru_cache (python#98591) pythongh-99127: Allow some features of syslog to the main interpreter only (pythongh-99128) pythongh-82836: fix private network check (python#97733) Docs: improve accuracy of socketserver reference (python#24767) ...
Fixed by 131801d |
The _PyObject_SIZE() and _PyObject_VAR_SIZE() macros should be converted to functions: see PEP 670 for the rationale.
My problem is that I don't know if the return type should be signed (Py_ssize_t) or unsigned (size_t).
CPython usage of _PyObject_SIZE():
__sizeof__()
methods.PyObject_Malloc(_PyObject_SIZE(tp))
andgc_alloc(_PyObject_SIZE(tp), presize)
where the first argument type issize_t
.CPython usage of _PyObject_VAR_SIZE():
_PyDebugAllocatorStats(..., _PyObject_VAR_SIZE(&PyTuple_Type, len))
where the argument type issize_t
.To get a container length, the C API uses signed type (
Py_ssize_t
): PyList_Size(), PyDict_Size(), Py_SIZE(), etc.To allocate memory, the C API prefers unsigned type (
size_t
): PyMem_Malloc(), PyObject_Realloc(), etc.Python allocator functions reject size greater than
PY_SSIZE_T_MAX
:Some "sizeof" functions freely mix signed and unsigned types. Example:
blocks
andsizeof(block)
are unsigned, butres
is signed.Another problem is that _PyObject_VAR_SIZE() has an undefined behavior on integer overflow. Maybe it should return
SIZE_MAX
on oveflow, to make sure that Python allocator function fail (returnNULL
)?Linked PRs
The text was updated successfully, but these errors were encountered: