STINNER Victor <[email protected]> added the comment:
Example:
---
struct Point { int x; int y; int z; };
int main()
{
struct Point p = {1};
return p.y;
}
---
gcc -O0 produces this machine code which sets p.y to 0 and p.z to 0:
---
Dump of assembler code for function main:
0x0000000000401106 <+0>: push rbp
0x0000000000401107 <+1>: mov rbp,rsp
0x000000000040110a <+4>: mov QWORD PTR [rbp-0xc],0x0
0x0000000000401112 <+12>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000401119 <+19>: mov DWORD PTR [rbp-0xc],0x1
0x0000000000401120 <+26>: mov eax,DWORD PTR [rbp-0x8]
0x0000000000401123 <+29>: pop rbp
0x0000000000401124 <+30>: ret
---
gcc -O3 heavily optimize the code, it always return 0, it doesn't return a
random value from the stack:
---
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000401020 <+0>: xor eax,eax
0x0000000000401022 <+2>: ret
---
The "C99 Standard 6.7.8.21" says:
If there are fewer initializers in a brace-enclosed list than there are
elements or members of an aggregate, or fewer characters in a string literal
used to initialize an array of known size than there are elements in the array,
the remainder of the aggregate shall be initialized implicitly the same as
objects that have static storage duration.
The C99 standard says that p.y and p.z must be set to 0.
I'm talking about the specific C syntax of a structure static initialization:
"struct MyStruct x = {...};".
If "Py_buffer data = {NULL, NULL};" is allocated on the stack, all "data"
Py_buffer members are set to 0 or NULL:
typedef struct bufferinfo {
void *buf;
PyObject *obj; /* owned reference */
Py_ssize_t len;
Py_ssize_t itemsize; /* This is Py_ssize_t so it can be
pointed to by strides in simple case.*/
int readonly;
int ndim;
char *format;
Py_ssize_t *shape;
Py_ssize_t *strides;
Py_ssize_t *suboffsets;
void *internal;
} Py_buffer;
If we want to add a version member to this structure, I would suggest to
enforce the usage of a static initialization macro or an initialization
function, like:
"Py_buffer data; PyBuffer_Init(&data);"
or
"Py_buffer data = PyBuffer_STATIC_INIT;"
The problem of the macro is that it is not usable on Python extensions was are
not written in C or C++ (or more generally to extensions which cannot use
macros).
--
A different approach is to use an API which allocates a Py_buffer on the heap
memory, so if the structure becomes larger tomorrow, an old built C extensions
continues to work:
Py_buffer *data = PyBuffer_New();
// ... use *data ...
PyBuffer_Free(data);
PyBuffer_New() can initialize the version member and allocates the proper
memory block size.
The best is if the "... use *data ..." part is only done with function calls :-)
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue45459>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com