Frank Heckenbach replied:
are particular Pascal structures that shouldn't be zeroed by this technique (apart from dynamic arrays)?
Any kind of schemata, which include dynamic arrays ans strings
Also files and objects.
There is a built-in procedure `Initialize' to (re-)initialize any variable, so you could theoretically zero out everything, then initialize it again, but I'm not sure if I should have mentioned this. ;-) In any case, you'll do some extra work (init, zero, init again) ...
But I agree, in this case I'd recommend a `for' loop, too.
PROCEDURE zero(VAR param; ch : char; size : longint); asmname 'memset';
BEGIN NEW( Test1, a ); writeln(sizeof(Test1^)); zero(Test1^,#0,sizeof(Test1^)); END.
OK - that's helpful. My example was trivial, but in practice I'm trying to zero very large arrays of large records which I very time consuming with loops and type-matched assignments.
So I do new(anyvar,x, y); zero(anyvar^,#0,sizeof(anyvar)); initialize(anyvar);
.. and because initialize is a built-in, it doesn't need any declaring. BUT ... when I run with electric-fence I get a SIGSEGV in memset. Doing some experimentation, it appears that each dynamic array dimension uses an extra 4 words. So if I amend my zero function call as follows ...
zero(anyvar^,#0,sizeof(anyvar)-8);
... the problem goes away. In this case, the Initialize() call doesn't seem to make any difference.
Am I right in assuming that the dynamic array sizing is tacked on the end of the storage so deducting 4 words per dimension is the right approach?
Is Initialize() only required after I've zeroed a string or a record containing a string?
Finally, given that Initialize can very usefully take any variable as a parameter, it's a shame that it doesn't actually do the zeroing. Is there another built-in I haven't spotted that will do this without be having to explicitly worry about the number of dimensions the dynamic arrays have?
David Wood, QinetiQ Farnborough.
The Information contained in this E-Mail and any subsequent correspondence is private and is intended solely for the intended recipient(s). For those other than the recipient any disclosure, copying, distribution, or any action taken or omitted to be taken in reliance on such information is prohibited and may be unlawful.
Wood David wrote:
Am I right in assuming that the dynamic array sizing is tacked on the end of the storage so deducting 4 words per dimension is the right approach?
Schemata contain their discriminants just as declared, i.e., 4 bytes (not words!?) for `Integer' on most systems. They're similar to records, with the discriminants at the front(!).
Is Initialize() only required after I've zeroed a string or a record containing a string?
Maurice and I have said which types require initialization (besides types with explicit initializers, of course). But the list is not guaranteed to be complete for all times ...
Finally, given that Initialize can very usefully take any variable as a parameter, it's a shame that it doesn't actually do the zeroing.
One doesn't always want to do the zeroing (which can be substantially more work for large structures) when initializing. Using `FillChar' and `Initialize' explicitly is just what the compiler would do if it would include the zeroing (unless you'd expect it, e.g., to initialize reals to the floating point 0.0 representation which AFAIK isn't necessarily all zero bytes).
BTW, EP initializers would help here since you could just initialize the array to zero. Unfortunately, they're not completely implemented in GPC yet (and this case is missing) ...
- If sizeof() reports a dynamic variable (e.g.. an array of 3 doubles) to
be, say, 28 bytes, which we understand to be 3 x 8 + 4 for the dynamic size, the total size of the Pascal storage area is 28. So why should linking with efence produce a SIGSEGV anyway when using memset on this area?
The problem is with the untyped parameter: It's basically not clear what should be passed, the whole schema or just the array. When the whole schema is passed, `SizeOf' would be correct, but when the array is passed, you'd need the size of the array only (which, AFAICS, cannot be easily obtained).
If the parameter is declared either as `Dyn_arr' or as an open/conformant array (`array of Integer' or `array [a .. b: Integer] of Integer'), it would be clear either way. But an untyped parameter principally allows for both (yet another caveat with untyped parameters).
I think I agree that passing the whole schema would be more reasonable. If there's consensus, I think we can make it the (documented) behaviour in future GPC versions. (Perhaps you can write some test programs ...)
Frank
Wood David wrote:
OK - that's helpful. My example was trivial, but in practice I'm trying to zero very large arrays of large records which I very time consuming with loops and type-matched assignments.
(1) What about this: get a pointer to the first array element and then clear sizeof-array-element * array-size bytes ?
(2) With modern risc processors, the time delay for operations on large data sets is typically in memory stalls, not in processor instructions. Are your records densely packed or unaligned on the processor's "natural" data bounds ? Did you actually try to zero the array in a for loop per record (with a low-level routine if you want) ? Did you profile the software ?
Regards,
Adriaan van Os