John E. Malmberg wrote:
The patch that I submitted is needed to eliminate a data corruption
issue that should be affecting more than just VMS.
If I have diagnosed this wrong, please let me know.
just a wild conjecture from the peanut gallery.
There are some pretty subtle tricks played in the memory allocation areas,
which might explain why nobodys responding; most dont understand it all
deeply,
and given that tests pass so successfully, its hard to imagine an error
of the size
you suggest could be universally present.
(or it could be august vacations, or firefighting at day jobs)
In VMS this data corruption is only visible in one apparent test
script where it causes Perl to exit with an access violation after a
pointer gets stepped on. So it is easy to see how it might get missed.
What I have found after Nicholas Clark pointed me in the right
direction, is that in this case is that the allocation size for the
sv_u.svu_array member appears to be too small.
The size of the allocated or reallocated array is controlled by the
xhv_max member.
DBG> exam hv->sv_any->xhv_max
HV\Perl_hv_iternext_flags\hv->sv_any->xhv_max: 7
The actual calculation is for the array size =
PERL_HV_ARRAY_ALLOC_BYTES(HvMAX(hv) + 1) + sizeof(struct xpvfhv_aux)
HvMAX(hv) = 7 from above.
So PERL_HV_ARRAY_ALLOC_BYTES results in:
(8 * sizeof(HE*) + sizeof(struct xpvfhv_aux)
The size of a Pointer type on VMS is 4 bytes. And the size of the
struct xpvfhv is 12 bytes. This results in (8 * 4) + 12 or 48 bytes.
A pointer to the xpvfhv is then stored in hv->sv_u.svu_array[8].
The size of the svu_array type is 12 bytes, so the offset is 12 *
(8-1) is 84 which is a bit beyond the 48 bytes that was allocated.
It appears to me that macro PERL_HV_ARRAY_ALLOC_BYTES should be using
the size of the HE structure instead of the size of a pointer to that
structure.
If that were the calculation, than 108 bytes would have been allocated
or reallocated for the array member, which looks like the correct size.
This starts to hint at the complexities im refering to:
http://gisle.aas.no/perl/illguts/
As a special case we also have /SvIV/ and /SvNV/ types that only have
room for a single integer or a single double value. These are special in
that the PVX/CUR/LEN fields are not present even if the ANY pointer
actually points to the ghostual incarnation of them. This arrangement
makes it possible for code to always access the IVX/NVX fields at a
fixed offset from where the SV field ANY points.
this same trick is also used and described in sv.c
1157 #define
new_body_type(TYPE,lctype) \
1158 S_new_body(aTHX_ (void**)&PL_ ## lctype ##
_arenaroot, \
1159 (void**)&PL_ ## lctype ##
_root, \
1160 sizeof(TYPE))
1161
1162 #define del_body_type(p,TYPE,lctype) \
1163 del_body((void*)p, (void**)&PL_ ## lctype ## _root)
1164
1165 /* But for some types, we cheat. The type starts with some
members that are
1166 never accessed. So we allocate the substructure, starting at
the first used
1167 member, then adjust the pointer back in memory by the size of
the bit not
1168 allocated, so it's as if we allocated the full structure.
1169 (But things will all go boom if you write to the part that is
"not there",
1170 because you'll be overwriting the last members of the
preceding structure
1171 in memory.)
1172
1173 We calculate the correction using the STRUCT_OFFSET macro.
For example, if
1174 xpv_allocated is the same structure as XPV then the two
OFFSETs sum to zero,
1175 and the pointer is unchanged. If the allocated structure is
smaller (no
1176 initial NV actually allocated) then the net effect is to
subtract the size
1177 of the NV from the pointer, to return a new pointer as if an
initial NV were
1178 actually allocated.
1179
1180 This is the same trick as was used for NV and IV bodies.
Ironically it
1181 doesn't need to be used for NV bodies any more, because NV is
now at the
1182 start of the structure. IV bodies don't need it either,
because they are
1183 no longer allocated. */
1184
1185 #define
new_body_allocated(TYPE,lctype,member) \
1186 (void*)((char*)S_new_body(aTHX_ (void**)&PL_ ## lctype ##
_arenaroot, \
1187 (void**)&PL_ ## lctype ##
_root, \
1188 sizeof(lctype ## _allocated))
- \
1189 STRUCT_OFFSET(TYPE,
member) \
1190 + STRUCT_OFFSET(lctype ## _allocated, member))
1191
sv.h also has some clues
286 #if 0
287 typedef struct xpv xpv_allocated;
288 #else
289 typedef struct {
290 STRLEN xpv_cur; /* length of svu_pv as a C string */
291 STRLEN xpv_len; /* allocated size */
292 } xpv_allocated;
293 #endif
294
Im not saying the explanation is here, but certainly some clues
and deeper understanding are.
-John
[EMAIL PROTECTED]
Personal Opinion Only
hth,
Jim Cromie