hookenz
hookenz

Reputation: 38879

Should I avoid placing large objects on the stack?

In a non-recursive function is it generally OK to place large data types on the stack?

One place where it is handy is in a C function that needs to clean things up.

e.g. I have a C function that allows me to read/write arbitrary packets of data like this.

int do_something()
{
  char buf[9000];
  struct ot_packet_t p;

  pkt_init(&p);
  pkt_set_type(&p, "WDAT");
  pkt_write_uint32(&p, some_var);
  pkt_write_data(&p, some_data, some_len);

  // other stuff...
  // if need to early exit... buf & p cleaned up.  An RAII approach.

  send_packet(buf, pkt_get_length(&p));
}

I've tagged this question with C++ as well as it could apply to C++ too. Although at least on C++ I would generally use auto_ptr to clean up larger objects allocated on the heap. In C I don't think this is as tidy right?

Upvotes: 3

Views: 539

Answers (2)

Ben Zotto
Ben Zotto

Reputation: 71008

"It depends." On the machine, the device, the size of the block, and how big the stack already is beneath you.

In your example, a ~9k block in a nonrecursive function will pretty much always be fine. (Exceptions here would be small embedded devices, or if you had lots of other functions that were doing the same thing on the same stack.)

As a purely personal rule of thumb, I generally don't use the stack for buffers of anything above a few K in normal application-level code. If you're doing packet transfer as in your example, and it was in a loop, you might see performance overhead from doing a dynamic allocation every time, so you'd either keep it on the stack, keep a static buffer somewhere, or some sort of reusable pool of buffers to use.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 753515

In a single-threaded application on a main-stream PC, then there isn't much need to be concerned: a few KiB here, a few Kib there; eventually, maybe, you reach a MiB or two on the stack. The stack grows automatically with minimal cost to the application.

If you're dealing with a multi-threaded application, things change. Each thread has its own stack, and (as I understand it) that stack size is fixed when the thread starts. If you start cluttering the thread's stack with large local variables, you may consume all the stack and run out of space. Therefore, it is better to use dynamic memory allocation for the larger objects to avoid running into such problems. Since you can can also do dynamic allocation for the single-threaded application, if there's a reasonable chance the program will evolve into a multi-threaded program, then maybe you should use dynamic allocation from the start. Note that dynamic allocation is slower than automatic allocation on the stack.

If you're dealing with a system that has limited memory, then you want to avoid creating large objects, period. You have to worry, at least, about how many exist at any one time, and make sure that they are released as soon as possible.

Upvotes: 4

Related Questions