14.6.1.2145 RESIZE MEMORY

( a-addr1 u -- a-addr2 ior )

Change the allocation of the contiguous data space starting at the address a-addr1, previously allocated by ALLOCATE or RESIZE, to u address units. u may be either larger or smaller than the current size of the region. The data-space pointer is unaffected by this operation.

If the operation succeeds, a-addr2 is the aligned starting address of u address units of allocated memory and ior is zero. a-addr2 may be, but need not be, the same as a-addr1. If they are not the same, the values contained in the region at a-addr1 are copied to a-addr2, up to the minimum size of either of the two regions. If they are the same, the values contained in the region are preserved to the minimum of u or the original size. If a-addr2 is not the same as a-addr1, the region of memory at a-addr1 is returned to the system according to the operation of FREE.

If the operation fails, a-addr2 equals a-addr1, the region of memory at a-addr1 is unaffected, and ior is the implementation-defined I/O result code.

See:

Testing:

T{ 50 CHARS ALLOCATE SWAP addr ! -> 0 }T
addr @ 50 write-char-mem addr @ 50 check-char-mem

\ Resize smaller does not change content.
T{ addr @ 28 CHARS RESIZE SWAP addr ! -> 0 }T
addr @ 28 check-char-mem

\ Resize larger does not change original content.
T{ addr @ 100 CHARS RESIZE SWAP addr ! -> 0 }T
addr @ 28 check-char-mem

\ Resize error does not change addr
T{ addr @ -1 RESIZE 0= -> addr @ <FALSE> }T

T{ addr @ FREE -> 0 }T
T{ HERE -> datsp @ }T    \ Data space pointer is unaffected

ContributeContributions

JimPetersonavatar of JimPeterson [429] Resizing to/from Zero Address UnitsRequest for clarification2026-05-18 19:50:35

No mention is made, here or for ALLOCATE, as to what happens when the specified size is zero. I can see cases where data structures may do so (perhaps inadvertently). Can we assume that such things will work properly? Should it be explicitly stated to work, or is it assumed to do so, since there is no verbiage stating otherwise?

(If the standard declared that resizing to 0 units must return the a-addr2 equal to 0, then RESIZE would be the only necessary word, as ALLOCATE could be 0 SWAP RESIZE and FREE could be 0 RESIZE NIP)

AntonErtlavatar of AntonErtl

That's a good point. AFAIK POSIX and C have tightened the requirements (i.e., given more guarantees to users) for malloc() and realloc(). It may be a good idea to look at what standard C guarantees now and maybe tighten allocate and resize, too. As for existing practice, many Forth implementations call malloc() and realloc(), respectively, so they implement these guarantees already.

AntonErtlavatar of AntonErtl

But who is going to write the proposal?

ruvavatar of ruv

Please note, in practice, 0 is not an addr. And we have a proposal to formally exclude zero from the addr data type.

It should probably be stated that if a program relies on resize never returning 0 on success, then it has an environment dependency.

And, in the stack diagrams we should indicate 0 separately from addr. For resize it should be:

  • ( a-addr1|0 u -- a-addr2|0 ior )

Or, a more arrow option:

  • ( a-addr1|0 u\0 -- a-addr2 ior | a-addr1|0 0 -- a-addr2|0 ior ) that is, it may return 0 instead of a-addr only when the new size is 0.

An even more arrow option:

  • ( a-addr1|0 u\0 -- a-addr2 0 | a-addr1|0 0 -- a-addr2|0 0 | a-addr1|0 0 -- x x ior\0 ) that is, if the top output parameter is not 0, other two output parameters are unspecified cells.

ruvavatar of ruv

If the standard declared that resizing to 0 units must return the a-addr2 equal to 0

Regarding must return 0. It seems, this would make most existing systems non-standard and would complicate some implementations.

AntonErtlavatar of AntonErtl

I have now looked up C23. It says (for all allocation functions it defines):

If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned to indicate an error, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.

It says about realloc():

If ptr [the input pointer] is a null pointer, the realloc function behaves like the malloc function for the specified size.

It also says:

Otherwise, [...] if the size [the input parameter for the new size] is zero, the behavior is undefined.

That sounds pretty idiotic and contradicts the general guarantee; interestingly, for malloc(), C23 does not undefine the result if size is zero.

POSIX-2024 gives some additional guarantees, but they are marked as obsolescent, so it's not a good idea to take these as inspiration for future Forth standards.

I think that if we want to say anything about the behaviour if u=0, it should be the general guarantee of C23.

What we should be adding to resize is the guarantee that realloc() makes when ptr is a null pointer.

Reply New Version