5

It's common to run into these errors during compile time

Stack offset of 6344 exceeded max offset of 4096 by 2248 bytes, please minimize large stack variables

or these errors during run time

Program failed to complete: Access violation in stack frame 3 at address 0x200003fe0 of size 8 by instruction #28386

Both of these indicate that the stack space usage exceeds the Solana max of 4096 bytes.

1 Answer 1

8

Box Accounts

Boxing accounts in #[Accounts] struct moves the account variables from the stack to the heap.

This however requires you to be able to deserialize the account with an #[account] type.

Eg

account: UncheckedAccount<'info>

becomes

account: Box<Account<'info, MyAccount>>

The trade-off is it will use more compute units to deserialize and validate the account data.

remaining_accounts

If you can't Box and deserialize accounts (they're SystemProgram owned, or you're too lazy to write out the serialization format), then don't include the account explicitly in #[Accounts] and manually pull it out of ctx.remaining_accounts in the body.

#[inline(never)]

The 4KB limit is on each stack frame. Each function call uses 1 stack frame, so if you have a beefy function it could very well exceed 4KB in stack space.

One trick is to break apart the function into sub-functions, then annotate the sub-functions with #[inline(never)] macro.

This

fn big() {
  // Do stuff 1
  // Do stuff 2
  // Do stuff 3
}

becomes

#[inline(never)]
fn stuff1() {
  // Do stuff 1
}

#[inline(never)]
fn stuff2() {
  // Do stuff 2
}

#[inline(never)]
fn stuff3() {
  // Do stuff 3
}

fn big() {
  stuff1();
  stuff2();
  stuff3();
}

Boxing variables

If you have functions that allocate large structs, Box::new() will move them from the stack to the heap.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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