Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 563 Vote(s) - 3.54 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Stack vs. Heap storage

#1
In C and it's derivatives, (as well as most, if not all other languages) variables are stored in two separate ways. Static types (often called fixed or fixed length) are stored on the "stack", whereas dynamic storage (namely Objects and their properties in any OO language like C++, C#, Python, Ruby, etc) is handled by the heap. There are significant pros and cons to both systems, and it's good to know when to use one over the other when you're the one manually allocating all the memory.

The Stack

The stack is a special place in memory that stores local variables (i.e. temporary; this is important) created by each function in your program (main() included). The stack is what's commonly called a LIFO structure, meaning "last in, first out", and it's managed entirely by the CPU, unless explicitly called upon.

Whenever a local variable is declared inside a function, said variable is pushed to the stack. When that function returns, all the variables pushed to the stack that the function created are freed from memory (you could also say they're deleted). When the space that a variable is taking up inside the stack is freed, that region immediately becomes available to other stack variables.

A quick demonstration of the stack is as follows:

Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.


The Heap

The heap is another region of memory available to your program that is not automatically managed for you, and is not optimized by the CPU. It's often referred to as "free-floating" memory, and is larger than the stack. To allocate memory to the heap, you must do so manually with the standard library malloc() or calloc() functions. Once memory has been allocated to the heap, you are responsible for clearing it with the free() function (also stdlib) to avoid a

[To see links please register here]

.

Contrary to the stack, there is no size limit for variables stored in the heap except for the physical limit of the computer your program is running on. Heap variables, again unlike those in the stack, are passed by using pointers (which themselves are stored on the stack, and reference the value in the heap) instead of passing by value, as you would with a stack variable. In light of these points, heap storage is just a bit slower than stack. This difference in speed can appear negligible in small programs, but it can add up as programs get larger and more complex. Finally, once created, heap variables are accessible anywhere in your program, essentially putting them in a global scope.

A demonstration of heap storage is as follows. Obviously, this isn't the optimal way to write a program with this functionality, but it serves as a good demonstration:

Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.


Pros, cons, and use cases

Now that we've gone over what does what, we can list the pros and cons of both storage methods, as well as use cases.

Stack storage
Pros: automatically allocated and freed, faster, CPU optimized
Cons: limited variable size (varies by OS), variables are fixed size

Most commonly, you should use the stack when dealing with relatively small variables that only need to exist for the lifetime of a function. It's easier and faster, so you might as well utilize it.

Heap storage
Pros: global access to variables, only size limit is the system's physical capacity, variables can be resized
Cons: slightly slower read/write operations, manual allocation/deallocation

Again generally speaking, you should use the heap when you need to allocate a large block of memory (e.g. a large array, a struct with lots of members, etc) and/or you need to keep it around for a long period of time, or access it globally.
Reply

#2
You have an error in your code,

Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.

Pointers have fixed size of 32 or 64 bits and if you only alloc for 32 bit, strcpy will cause an overflow
Reply

#3
Quote:(02-01-2017, 12:51 PM)silur Wrote:

[To see links please register here]

You have an error in your code,

Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.

Pointers have fixed size of 32 or 64 bits and if you only alloc for 32 bit, strcpy will cause an overflow

Code runs fine; would this be undocumented behaviour?
Reply

#4
it's documented, the code is not that complicated to cause a segfault, you can even write data to a null pointer and have chance to read from it, but actually it'll just write into some random point of the RAM and eventually cause a crash
Reply

#5
Wow. This is actually a really interesting topic, and demonstrates one of the nuanced magical differences between an char pointer and a char array.

In fact, char* and char[] aren't _exactly_ the same thing, as many people treat them to be. One of those differences is how the sizeof keyword handles them. char[] actually maintains size information along with it. This causes the sizeof operator to evaulate the actual byte size (not length) of the underlying array, whereas the sizeof a char* will always be the length of the pointer, just like how sizeof char will be the size of a char. Let's take a look at some simplified code...


Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.


We're allocating a memory region that can contain two characters, and storing the address in the pointer called str. Afterwards, we're placing our string Sinisterly\0 on the stack, and we'll point to it with name. Let's compile with
gcc -O0 -ggdb main.c -o main

and load it up in your disassembler of choice


Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.


There's some really fun stuff going on here. First, lets talk about the sizeof keyword. As we mentioned before, the sizeof keyword runs off static information that's known at compile time. Whats _really_ cool about this, is that it doesnt even assemble as a function call. It produces _literals_ for the two printf calls in which it is used:


Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.


Now, as we mentioned before, we're looking at sizeof a pointer with str, not the size of the array to which it points. We'll notice that i modified OP's code slightly to allocate 2 characters on the heap. And we confirm that we're looking at the 8 bytes of a pointer, not the 2 bytes of a size-two array.

Then, since the second data type is a magical char[] and not a pointer, in this case _we do_ print the length, which comes out to be the literal 0xb, or 11 dec. Compiled right into the code, even at O0 :smile:

There's some other mega interesting stuff too. Look at how the name array is initialized at 0x004005fe. Most of the string fits in rax, so we move it right on in. Very cool.

Notice that in both cases, when we're calling the strlen, we are using pointers. This interchangeability is where most C/C++ get tripped up and treat char* and char[] as the same. And of course, our output is as expected:


Hidden Content
You must

[To see links please register here]

or

[To see links please register here]

to view this content.


Note that strlen doesnt include the trailing null terminator, hence the results being one-off of whats actually in memory.
Reply

#6
This is not accurate for a few reasons. The stack is simply a part of the heap. When a program is loaded into memory, everything is done at once (similar to a stack of plates, hence the name). The slot in memory is set aside for the programs memory, instruction sets, ect (in that order btw, fairly important). At the beginning of the instruction set, and offset is given that determines where in memory the program is, and then the ESP register is used to determine where in the program we are currently (fucking Pentium pro).

If you want to have some serious fun, the ESP register is actually signed. You can send it into negatives and start accessing instruction sets of other programs.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through