4

I was reading Solidity's Layout in Memory docs, and I was rather surprised to learn that:

Solidity always places new objects at the free memory pointer and memory is never freed (this might change in the future).

I'm confused. Doesn't memory get flushed across contracts? Say you have an upgradeable proxy that delegate calls to an implementation contract. In this case, we use the "returndatasize" and "returndatacopy" EVM instructions to get hold of the return data. Aren't we doing that precisely because there is no other way to access the return data?

Furthermore, from the same doc:

There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifetime, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one should not expect the free memory to point to zeroed out memory.

So which one is it? Does Solidity free memory or not?

1

Solidity always places new objects at the free memory pointer and memory is never freed (this might change in the future).

This means simply that memory management in Solidity is currently very rudimentary. The compiler maintains a pointer to the end of the last allocated block and that's it. Allocating a new memory variable means moving that pointer forward.

The compiler never tries to reclaim already allocated memory. Even when all references to your memory variable go out of scope, there's no mechanism that would detect it and mark the space as available for reuse.

This is true for the duration of a single external call to the contract. Each new call starts with zeroed memory and freshly initialized free memory pointer.

There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifetime, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one should not expect the free memory to point to zeroed out memory.

This part refers to a small optimization the compiler performs when it needs a very short-lived memory block for the current operation. Instead of properly allocating it by updating the free memory pointer, it just writes past the pointer, knowing that the memory there is not in use. The text warns you that if you try to read from this area of unallocated memory using inline assembly, you might find some leftovers from such an operation and you should not assume that the memory there is always zeroed-out.

2
  • Great explanation, thanks. But how does the compiler recover memory vars after it performs a contract call? Say that (1) you define an array in memory, then (2) you call an external contract, thus zeroing out the the memory, then (3) you come back to the original contract and attempt to do some work with the previously defined array. How does the compiler recover it? Sep 5 at 22:46
  • 1
    No, each call has its own memory space and this space is only released when that call ends. Making another external call does not affect the memory in the current call (other than having the return data copied to the memory location indicated in the CALL opcode). At point (3) your contract gets back to the memory state it had before the call and can continue. The array will not be recovered.
    – cameel
    Sep 6 at 10:46
2

Each smart contract call have its own empty and clean (zeroed) memory. In the middle of the call your Solidity Assembly code should not assume next memory allocation is zeroed.

FYI, first 64 bytes called "scratch space", it is used for hashing mapping keys. Next 32 bytes (at 0x40 offset) used to store free memory pointer. So allocate new buffer of size length as following:

let ptr := mload(0x40)
mstore(0x40, add(ptr, length))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.