Why is heap-based buffer overflow difficult than stack-based? Also, what is the difference between them?
I know that memory is allocated dynamically in case of heaps but, is that it?
Related
I have a small buffer of 1024 bytes that I am using to store temporary data in and then write to a larger buffer. I am reusing that small buffer several times.
Is there any performance benefit to creating this buffer on the heap rather than the stack?
It's existing code so it was done on the heap but I'm not sure if it would be faster to use the stack or what exactly the reasoning was to using the heap in the first place.
Any ideas? This is C code.
If you are writing code for a very small system, you may need to get the buffer using malloc (or one of the related routines, such as calloc) so that you do not use limited stack space.
Otherwise, on modern systems, 1024 bytes is a modest amount of stack space to use, and creating a buffer on the stack is typically faster than using malloc. (A normal malloc call requires at least some amount of bookkeeping work that stack allocation does not. However, if a routine merely allocates a fixed-size buffer with malloc, uses it, and frees it, a compiler might optimize the buffer to a stack allocation anyway, in which case they would be equivalent.)
For reference, on macOS, Appleās tools default to 8 MiB of space for the main stack and 2 MiB for each thread.
In general, stack allocation is always faster than heap allocation.
This is because stack allocation is as easy as a single write to the stack pointer, whereas dynamic memory allocation contains a lot of overhead code during allocation - malloc has to go look for the next free segment, possibly also handling issues with fragmentation etc.
If you re-use a buffer, you should make sure to only allocate it once, no matter where you allocate it. This might be in favour of the heap, since heap-allocated variables don't go out of scope.
As for accessing memory once it is allocated, the stack and heap should perform identically.
Most importantly, allocating a large chunk of data on the stack isn't recommended, since it has a limited size. 1024 bytes is fairly large, so the recommended practice would be to store it on the heap for that reason alone.
This question already has answers here:
What and where are the stack and heap?
(31 answers)
Closed 8 years ago.
I've always thought that heap allocation is needed for allocating data structures with sizes that aren't known at compile time. But I recently learned about alloca, which allows for dynamic allocation on the stack. So, if heap allocation isn't needed for allocation of dynamic sizes, are there things for which heap allocation is necessary? My first thought is that resizing data structures may be difficult, but I'm not sure whether it's impossible or not without using the heap.
It's about live time. Objects on the heap live until you free() them. Objects allocated with alloca live in the current stack frame until your function returns.
Resizing of data on the heap will cause a new allocation if the first allocation did not reserve sufficcient memory. This will give the first heap item back to the free list. That is impossible in the stack frame. There is no realloc pendant.
BTW: There is no need that objects on the heap are of dynamic size. The function signature of malloc takes a size parameter that allows you to calculate the size at run-time. But you often allocate object without a dynamic size. e.g.
typedef struct {
int a;
char s[3];
} example;
example *ex = malloc(sizeof(example));
free(ex);
Edit: Although you could allocate again and again on the stack unless you get a stackoverflow the semantic differs from realloc. It wouldn't be possible to give the space back when a realloca should allocate the for a larger size. It's even impossible to shrink the size. The reason for both is the mechanismn how alloca works. There is no free list and there are no chunks on the stack that are managed like heap objects. It's just changing the stack pointer that gives space for the result of alloca.
If you restrict yourself to using the stack for memory then you restrict the lifetime of your data to the lifetime of the scope they were conceived in. Yes you could make them global but then you have a fixed amount of memory for your data.
How about we reserve a large chunk of global memory? Well now you are just emulating the heap in a memory wasteful way.
Heap is not necessary, double is not necessary, int is not necessary, all that is needed is 0 and 1 and a Turning Machine.
Different programming models exists to efficiently create and maintain code. Code could exist with just about everything on the stack. Depending on how the OS/environment is set up, the stack does not run out any faster than heap. Memory is memory - it is just that typical OS's put more stringent limits on the stack size as it is more likely that code needing large stack is errant than correct.
Processors tend to be designed that way too, allowing a large, but limited stack, and a relatively enormous dynamic data space.
So for now, live with performing most variable large size allocations via malloc() and save alloca() for niche applications. Maybe in 20 years everything will be on the stack due to Dr. Whippersnapper latest programming model.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
What is the difference between stack over flow and stack crash. When stack crash occurs?
what is the heap over flow and heap crash.
What happens when stack over flow/heap over flow occurs?
A stack overflow is extensively discussed here and means an overflow condition when there's not enough stack memory and other data gets overwritten causing undefined behavior.
"Stack crash" is likely a synonymous of the first although I've heard it (or stack corruption) to indicate, mostly in a debugging environment, when the stack pointer gets corrupted causing all the debugging stack-related views to stall (and obviously also the debuggee as well).
A heap overflow doesn't usually happen except in some memory-pool-managed circumstances since, assuming the operating system is doing a good job, you will never get to overwrite a used memory chunk by having that marked as writable. If heap memory gets exhausted your system will likely tell you that and fail.
A heap crash might be defined as an invalid use of heap memory, e.g. access violation or accessing invalid addresses. It should fall in the broader terminology of memory corruption and storage violation (these might be linked to stack overflows).
Not sure where you've heard of these terms, especially "stack crash", but I wouldn't use it to avoid confusion.
I never heard about Stack crash.
In general there is two kind of errors with memory access :
you violate some memory protection (trying to write in a readonly
part or access a memory you mustn't)
you access a memory you have right on but in a bad way
Stack overflow is generally used when the program intentionally or not corrupts the stack content by overflowing a structure inside it. This is much like case (2).
It is also used when you overrun the stack, by interleaving to much function calls for example. This is much like case (1). Java for example gives you a StackOverflow exception in this case.
You also have both cases with heap. A buffer overflow is an example of accessing memory the bad way and corrupting data in the heap (if the buffer is in the heap). In this case we can say that it is a Heap overflow.
You can also try to access some memory in the Heap region of your process that is not currently allocated. This leads you to different scenarios depending of the virtual memory layer. Sometimes you are able to use the memory but as it has not been previously allocated it will leads you to a future memory corruption (not reported at the time it appears and difficult to trace back).
Sometimes the virtual memory layer will be able to detect your access violation and will abort your process (Unix can report it as Bus error or Segmentation fault).
You can also consume all the Heap space by allocating too much memory. This is a Heap exhaustion a kind of Heap overrun...
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to avoid memory allocations to construct the path for device
char *device;
const char *p;
char buf[PATH_MAX];
Witch method is memory less use
PATH_MAX
snprintf(buf, sizeof(buf) - 1, "/dev/%s", p);
device = &buf[0];
or
asprintf
asprintf(&device, "/dev/%s", p);
asprintf allocates the memory needed dynamically while the first method declares a (probably) larger buffer on the stack. So asprintf uses exactly as much bytes as needed and char buf[MAX] does not. But you have to make sure you free the memory allocated in asprintf yourself
The most significant difference is not the few bytes of memory, but where the memory is coming from and how you need to handle it afterwards.
buf is allocated on the stack, and if you return from the function your snippet is coming from, then device will not point to a valid memory location anymore. Corruption or a crash will be the most likely outcome. On the other hand, if you only use device inside the function, you won't have to free it afterwards. Also, stack-allocated memory is more efficient in general, although caching and optimizations may equal the picture.
asprintf allocates the memory from the heap, which means you can safely pass it around to all parts of your program as long as it runs. The downside is that you have to free it when you don't need it anymore or it will hang around forever and you have a memory leak (which might matter or not, depending on how many unfreed buffers are floating around). It's then your responsibility to free the memory.
But to answer your question: asprintf will allocate no more bytes than needed, and you don't have to specify a maximum size which might "feel" better. You probably shouldn't worry about a few bytes of stack memory extra though. How big is PATH_MAX? Half a kilobyte?
We have functions to allocate memory on stack in both in windows and Linux systems but their use is discouraged also they are not a part of the C standard? This means that they provide some non-standard behavior. As I'm not that experienced I cannot understand what could be the problem when allocating memory from stack rather then using heap?
Thanks.
EDIT: My view: As Delan has explained that the amount of stack allocated to a program is decided during compile time so we cannot ask for more stack from the OS if we run out of it.The only way out would be a crash.So it's better to leave the stack for storage of primary things like variables,functions,function calls,arrays,structures etc. and use heap as much as the capacity of the OS/machine.
Stack memory has the benefit of frequently being faster to allocate than heap memory.
However, the problem with this, at least in the specific case of alloca(3), is that in many implementations, it just decreases the stack pointer, without giving regard or notification as to whether or not there actually is any stack space left.
The stack memory is fixed at compile- or runtime, and does not dynamically expand when more memory is needed. If you run out of stack space, and call alloca, you have a chance of getting a pointer to non-stack memory. You have no way of knowing if you have caused a stack overflow.
Addendum: this does not mean that we shouldn't use dynamically allocate stack memory; if you are
in a heavily controlled and monitored environment, such as an embedded application, where the stack limits are known or able to be set
keeping track of all memory allocations carefully to avoid a stack overflow
ensuring that you don't recurse enough to cause a stack overflow
then stack allocations are fine, and can even be beneficial to save time (motion of stack pointer is all that happens) and memory (you're using the pre-allocated stack, and not eating into heap).
Memory on stack (automatic in broader sense) is fast, safe and foolproof compared to heap.
Fast: Because it's allocated at compile time, so no overhead involved
safe: It's exception safe. The stack gets automatically wound up, when exception is thrown.
full proof: You don't have to worry about virtual destructors kind of scenarios. The destructors are called in proper order.
Still there are sometimes, you have to allocate memory runtime, at that time you can first resort on standard containers like vector, map, list etc. Allocating memory to row pointers should be always a judicious decision.