mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Add comments about the need to avoid uninitialized bits in datatype values.
There was already one recommendation in the documentation about writing C functions to ensure padding bytes are zeroes, but make it stronger. Also fix an example that was still using direct assignment to a varlena length word, which no longer works since the varvarlena changes.
This commit is contained in:
@ -1680,6 +1680,15 @@ typedef struct
|
|||||||
itself.
|
itself.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Another important point is to avoid leaving any uninitialized bits
|
||||||
|
within data type values; for example, take care to zero out any
|
||||||
|
alignment padding bytes that might be present in structs. Without
|
||||||
|
this, logically-equivalent constants of your data type might be
|
||||||
|
seen as unequal by the planner, leading to inefficient (though not
|
||||||
|
incorrect) plans.
|
||||||
|
</para>
|
||||||
|
|
||||||
<warning>
|
<warning>
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Never</> modify the contents of a pass-by-reference input
|
<emphasis>Never</> modify the contents of a pass-by-reference input
|
||||||
@ -1723,7 +1732,7 @@ typedef struct {
|
|||||||
char buffer[40]; /* our source data */
|
char buffer[40]; /* our source data */
|
||||||
...
|
...
|
||||||
text *destination = (text *) palloc(VARHDRSZ + 40);
|
text *destination = (text *) palloc(VARHDRSZ + 40);
|
||||||
destination->length = VARHDRSZ + 40;
|
SET_VARSIZE(destination, VARHDRSZ + 40);
|
||||||
memcpy(destination->data, buffer, 40);
|
memcpy(destination->data, buffer, 40);
|
||||||
...
|
...
|
||||||
]]>
|
]]>
|
||||||
@ -1732,6 +1741,8 @@ memcpy(destination->data, buffer, 40);
|
|||||||
<literal>VARHDRSZ</> is the same as <literal>sizeof(int4)</>, but
|
<literal>VARHDRSZ</> is the same as <literal>sizeof(int4)</>, but
|
||||||
it's considered good style to use the macro <literal>VARHDRSZ</>
|
it's considered good style to use the macro <literal>VARHDRSZ</>
|
||||||
to refer to the size of the overhead for a variable-length type.
|
to refer to the size of the overhead for a variable-length type.
|
||||||
|
Also, the length field <emphasis>must</> be set using the
|
||||||
|
<literal>SET_VARSIZE</> macro, not by simple assignment.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -2345,13 +2356,16 @@ concat_text(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Always zero the bytes of your structures using
|
Always zero the bytes of your structures using <function>memset</>
|
||||||
<function>memset</function>. Without this, it's difficult to
|
(or allocate them with <function>palloc0</> in the first place).
|
||||||
|
Even if you assign to each field of your structure, there might be
|
||||||
|
alignment padding (holes in the structure) that contain
|
||||||
|
garbage values. Without this, it's difficult to
|
||||||
support hash indexes or hash joins, as you must pick out only
|
support hash indexes or hash joins, as you must pick out only
|
||||||
the significant bits of your data structure to compute a hash.
|
the significant bits of your data structure to compute a hash.
|
||||||
Even if you initialize all fields of your structure, there might be
|
The planner also sometimes relies on comparing constants via
|
||||||
alignment padding (holes in the structure) that contain
|
bitwise equality, so you can get undesirable planning results if
|
||||||
garbage values.
|
logically-equivalent values aren't bitwise equal.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user